VirtualBox

Changeset 12625 in vbox


Ignore:
Timestamp:
Sep 22, 2008 7:15:38 AM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
36901
Message:

IO breakpoints triggered after the fact.

Location:
trunk/src/VBox/VMM/VMMR0
Files:
2 edited

Legend:

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

    r12610 r12625  
    17751775        IoExitInfo.au32[0] = pVMCB->ctrl.u64ExitInfo1;
    17761776
    1777         /* If any IO breakpoints are armed, then we should check if a debug trap needs to be generated. */
    1778         if (pCtx->dr[7] & X86_DR7_ENABLED_MASK)
    1779         {
    1780             STAM_COUNTER_INC(&pVM->hwaccm.s.StatDRxIOCheck);
    1781             for (unsigned i=0;i<4;i++)
    1782             {
    1783                 if (    pCtx->dr[i] == IoExitInfo.n.u16Port
    1784                     &&  (pCtx->dr[7] & (X86_DR7_L(i) | X86_DR7_G(i)))
    1785                     &&  (pCtx->dr[7] & X86_DR7_RW(i, X86_DR7_RW_IO)) == X86_DR7_RW(i, X86_DR7_RW_IO))
    1786                 {
    1787                     SVM_EVENT Event;
    1788 
    1789                     Assert(CPUMIsGuestDebugStateActive(pVM));
    1790 
    1791                     /* Clear all breakpoint status flags and set the one we just hit. */
    1792                     pCtx->dr[6] &= ~(X86_DR6_B0|X86_DR6_B1|X86_DR6_B2|X86_DR6_B3);
    1793                     pCtx->dr[6] |= RT_BIT(i);
    1794 
    1795                     /* Note: AMD64 Architecture Programmer's Manual 13.1:
    1796                      * Bits 15:13 of the DR6 register is never cleared by the processor and must be cleared by software after
    1797                      * the contents have been read.
    1798                      */
    1799                     pVMCB->guest.u64DR6 = pCtx->dr[6];
    1800 
    1801                     /* X86_DR7_GD will be cleared if drx accesses should be trapped inside the guest. */
    1802                     pCtx->dr[7] &= ~X86_DR7_GD;
    1803 
    1804                     /* Paranoia. */
    1805                     pCtx->dr[7] &= 0xffffffff;                                              /* upper 32 bits reserved */
    1806                     pCtx->dr[7] &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15));    /* must be zero */
    1807                     pCtx->dr[7] |= 0x400;                                                   /* must be one */
    1808 
    1809                     pVMCB->guest.u64DR7 = pCtx->dr[7];
    1810 
    1811                     /* Inject the exception. */
    1812                     Log(("Inject IO debug trap at %VGv\n", pCtx->rip));
    1813 
    1814                     Event.au64[0]    = 0;
    1815                     Event.n.u3Type   = SVM_EVENT_EXCEPTION; /* trap or fault */
    1816                     Event.n.u1Valid  = 1;
    1817                     Event.n.u8Vector = X86_XCPT_DB;
    1818 
    1819                     SVMR0InjectEvent(pVM, pVMCB, pCtx, &Event);
    1820 
    1821                     STAM_PROFILE_ADV_STOP(&pVM->hwaccm.s.StatExit, x);
    1822                     goto ResumeExecution;
    1823                 }
    1824             }
    1825         }
    1826 
    18271777        /** @todo could use a lookup table here */
    18281778        if (IoExitInfo.n.u1OP8)
     
    19051855            if (RT_LIKELY(rc == VINF_SUCCESS))
    19061856            {
     1857                /* If any IO breakpoints are armed, then we should check if a debug trap needs to be generated. */
     1858                if (pCtx->dr[7] & X86_DR7_ENABLED_MASK)
     1859                {
     1860                    STAM_COUNTER_INC(&pVM->hwaccm.s.StatDRxIOCheck);
     1861                    for (unsigned i=0;i<4;i++)
     1862                    {
     1863                        if (    pCtx->dr[i] == IoExitInfo.n.u16Port
     1864                            &&  (pCtx->dr[7] & (X86_DR7_L(i) | X86_DR7_G(i)))
     1865                            &&  (pCtx->dr[7] & X86_DR7_RW(i, X86_DR7_RW_IO)) == X86_DR7_RW(i, X86_DR7_RW_IO))
     1866                        {
     1867                            SVM_EVENT Event;
     1868
     1869                            Assert(CPUMIsGuestDebugStateActive(pVM));
     1870
     1871                            /* Clear all breakpoint status flags and set the one we just hit. */
     1872                            pCtx->dr[6] &= ~(X86_DR6_B0|X86_DR6_B1|X86_DR6_B2|X86_DR6_B3);
     1873                            pCtx->dr[6] |= RT_BIT(i);
     1874
     1875                            /* Note: AMD64 Architecture Programmer's Manual 13.1:
     1876                             * Bits 15:13 of the DR6 register is never cleared by the processor and must be cleared by software after
     1877                             * the contents have been read.
     1878                             */
     1879                            pVMCB->guest.u64DR6 = pCtx->dr[6];
     1880
     1881                            /* X86_DR7_GD will be cleared if drx accesses should be trapped inside the guest. */
     1882                            pCtx->dr[7] &= ~X86_DR7_GD;
     1883
     1884                            /* Paranoia. */
     1885                            pCtx->dr[7] &= 0xffffffff;                                              /* upper 32 bits reserved */
     1886                            pCtx->dr[7] &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15));    /* must be zero */
     1887                            pCtx->dr[7] |= 0x400;                                                   /* must be one */
     1888
     1889                            pVMCB->guest.u64DR7 = pCtx->dr[7];
     1890
     1891                            /* Inject the exception. */
     1892                            Log(("Inject IO debug trap at %VGv\n", pCtx->rip));
     1893
     1894                            Event.au64[0]    = 0;
     1895                            Event.n.u3Type   = SVM_EVENT_EXCEPTION; /* trap or fault */
     1896                            Event.n.u1Valid  = 1;
     1897                            Event.n.u8Vector = X86_XCPT_DB;
     1898
     1899                            SVMR0InjectEvent(pVM, pVMCB, pCtx, &Event);
     1900
     1901                            STAM_PROFILE_ADV_STOP(&pVM->hwaccm.s.StatExit, x);
     1902                            goto ResumeExecution;
     1903                        }
     1904                    }
     1905                }
     1906
    19071907                STAM_PROFILE_ADV_STOP(&pVM->hwaccm.s.StatExit, x);
    19081908                goto ResumeExecution;
  • trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp

    r12610 r12625  
    21112111        }
    21122112
    2113         /* If any IO breakpoints are armed, then we should check if a debug trap needs to be generated. */
    2114         if (pCtx->dr[7] & X86_DR7_ENABLED_MASK)
    2115         {
    2116             STAM_COUNTER_INC(&pVM->hwaccm.s.StatDRxIOCheck);
    2117             for (unsigned i=0;i<4;i++)
    2118             {
    2119                 if (    pCtx->dr[i] == uPort
    2120                     &&  (pCtx->dr[7] & (X86_DR7_L(i) | X86_DR7_G(i)))
    2121                     &&  (pCtx->dr[7] & X86_DR7_RW(i, X86_DR7_RW_IO)) == X86_DR7_RW(i, X86_DR7_RW_IO))
    2122                 {
    2123                     uint64_t uDR6;
    2124 
    2125                     Assert(CPUMIsGuestDebugStateActive(pVM));
    2126 
    2127                     uDR6 = ASMGetDR6();
    2128 
    2129                     /* Clear all breakpoint status flags and set the one we just hit. */
    2130                     uDR6 &= ~(X86_DR6_B0|X86_DR6_B1|X86_DR6_B2|X86_DR6_B3);
    2131                     uDR6 |= RT_BIT(i);
    2132 
    2133                     /* Note: AMD64 Architecture Programmer's Manual 13.1:
    2134                      * Bits 15:13 of the DR6 register is never cleared by the processor and must be cleared by software after
    2135                      * the contents have been read.
    2136                      */
    2137                     ASMSetDR6(uDR6);
    2138 
    2139                     /* X86_DR7_GD will be cleared if drx accesses should be trapped inside the guest. */
    2140                     pCtx->dr[7] &= ~X86_DR7_GD;
    2141 
    2142                     /* Paranoia. */
    2143                     pCtx->dr[7] &= 0xffffffff;                                              /* upper 32 bits reserved */
    2144                     pCtx->dr[7] &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15));    /* must be zero */
    2145                     pCtx->dr[7] |= 0x400;                                                   /* must be one */
    2146 
    2147                     /* Resync DR7 */
    2148                     rc = VMXWriteVMCS(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
    2149                     AssertRC(rc);
    2150 
    2151                     /* Construct inject info. */
    2152                     intInfo  = X86_XCPT_DB;
    2153                     intInfo |= (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
    2154                     intInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_HWEXCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
    2155 
    2156                     Log(("Inject IO debug trap at %VGv\n", pCtx->rip));
    2157                     rc = VMXR0InjectEvent(pVM, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo), 0, 0);
    2158                     AssertRC(rc);
    2159 
    2160                     STAM_PROFILE_ADV_STOP(&pVM->hwaccm.s.StatExit, x);
    2161                     goto ResumeExecution;
    2162                 }
    2163             }
    2164         }
    2165 
    21662113        uint32_t cbSize = aIOSize[uIOWidth];
    21672114
     
    22212168            if (RT_LIKELY(rc == VINF_SUCCESS))
    22222169            {
     2170                /* If any IO breakpoints are armed, then we should check if a debug trap needs to be generated. */
     2171                if (pCtx->dr[7] & X86_DR7_ENABLED_MASK)
     2172                {
     2173                    STAM_COUNTER_INC(&pVM->hwaccm.s.StatDRxIOCheck);
     2174                    for (unsigned i=0;i<4;i++)
     2175                    {
     2176                        if (    pCtx->dr[i] == uPort
     2177                            &&  (pCtx->dr[7] & (X86_DR7_L(i) | X86_DR7_G(i)))
     2178                            &&  (pCtx->dr[7] & X86_DR7_RW(i, X86_DR7_RW_IO)) == X86_DR7_RW(i, X86_DR7_RW_IO))
     2179                        {
     2180                            uint64_t uDR6;
     2181
     2182                            Assert(CPUMIsGuestDebugStateActive(pVM));
     2183
     2184                            uDR6 = ASMGetDR6();
     2185
     2186                            /* Clear all breakpoint status flags and set the one we just hit. */
     2187                            uDR6 &= ~(X86_DR6_B0|X86_DR6_B1|X86_DR6_B2|X86_DR6_B3);
     2188                            uDR6 |= RT_BIT(i);
     2189
     2190                            /* Note: AMD64 Architecture Programmer's Manual 13.1:
     2191                             * Bits 15:13 of the DR6 register is never cleared by the processor and must be cleared by software after
     2192                             * the contents have been read.
     2193                             */
     2194                            ASMSetDR6(uDR6);
     2195
     2196                            /* X86_DR7_GD will be cleared if drx accesses should be trapped inside the guest. */
     2197                            pCtx->dr[7] &= ~X86_DR7_GD;
     2198
     2199                            /* Paranoia. */
     2200                            pCtx->dr[7] &= 0xffffffff;                                              /* upper 32 bits reserved */
     2201                            pCtx->dr[7] &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15));    /* must be zero */
     2202                            pCtx->dr[7] |= 0x400;                                                   /* must be one */
     2203
     2204                            /* Resync DR7 */
     2205                            rc = VMXWriteVMCS(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
     2206                            AssertRC(rc);
     2207
     2208                            /* Construct inject info. */
     2209                            intInfo  = X86_XCPT_DB;
     2210                            intInfo |= (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
     2211                            intInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_HWEXCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
     2212
     2213                            Log(("Inject IO debug trap at %VGv\n", pCtx->rip));
     2214                            rc = VMXR0InjectEvent(pVM, pCtx, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(intInfo), 0, 0);
     2215                            AssertRC(rc);
     2216
     2217                            STAM_PROFILE_ADV_STOP(&pVM->hwaccm.s.StatExit, x);
     2218                            goto ResumeExecution;
     2219                        }
     2220                    }
     2221                }
     2222
    22232223                STAM_PROFILE_ADV_STOP(&pVM->hwaccm.s.StatExit, x);
    22242224                goto ResumeExecution;
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