Changeset 47681 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- Aug 12, 2013 10:51:55 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/DBGFAll.cpp
r47671 r47681 24 24 #include "DBGFInternal.h" 25 25 #include <VBox/vmm/vm.h> 26 #include <VBox/err.h> 26 27 #include <iprt/assert.h> 27 28 … … 131 132 132 133 /** 134 * Checks if any of the hardware I/O breakpoints are armed. 135 * 136 * @returns true if armed, false if not. 137 * @param pVM The cross context VM structure. 138 */ 139 VMM_INT_DECL(bool) DBGFBpIsHwIoArmed(PVM pVM) 140 { 141 Assert(RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints) == 4); 142 /** @todo cache this! */ 143 return ( pVM->dbgf.s.aHwBreakpoints[0].u.Reg.fType == X86_DR7_RW_IO 144 && pVM->dbgf.s.aHwBreakpoints[0].fEnabled 145 && pVM->dbgf.s.aHwBreakpoints[0].enmType == DBGFBPTYPE_REG 146 ) 147 || ( pVM->dbgf.s.aHwBreakpoints[1].u.Reg.fType == X86_DR7_RW_IO 148 && pVM->dbgf.s.aHwBreakpoints[1].fEnabled 149 && pVM->dbgf.s.aHwBreakpoints[1].enmType == DBGFBPTYPE_REG 150 ) 151 || ( pVM->dbgf.s.aHwBreakpoints[2].u.Reg.fType == X86_DR7_RW_IO 152 && pVM->dbgf.s.aHwBreakpoints[2].fEnabled 153 && pVM->dbgf.s.aHwBreakpoints[2].enmType == DBGFBPTYPE_REG 154 ) 155 || ( pVM->dbgf.s.aHwBreakpoints[3].u.Reg.fType == X86_DR7_RW_IO 156 && pVM->dbgf.s.aHwBreakpoints[3].fEnabled 157 && pVM->dbgf.s.aHwBreakpoints[3].enmType == DBGFBPTYPE_REG 158 ); 159 } 160 161 162 /** 163 * Checks I/O access for guest or hypervisor breakpoints. 164 * 165 * @returns Strict VBox status code 166 * @retval VINF_SUCCESS no breakpoint. 167 * @retval VINF_EM_DBG_BREAKPOINT hypervisor breakpoint triggered. 168 * @retval VINF_EM_RAW_GUEST_TRAP guest breakpoint triggered, DR6 and DR7 have 169 * been updated appropriately. 170 * 171 * @param pVM The cross context VM structure. 172 * @param pVCpu The cross context CPU structure for the calling EMT. 173 * @param pCtx The CPU context for the calling EMT. 174 * @param uIoPort The I/O port being accessed. 175 * @param cbValue The size/width of the access, in bytes. 176 */ 177 VMM_INT_DECL(VBOXSTRICTRC) DBGFBpCheckIo(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, RTIOPORT uIoPort, uint8_t cbValue) 178 { 179 static uint8_t const s_abInvAlign[4] = { 0, 1, 7, 3 }; 180 uint32_t const uIoPortFirst = uIoPort; 181 uint32_t const uIoPortLast = uIoPortFirst + cbValue - 1; 182 183 184 /* 185 * Check hyper breakpoints first as the VMM debugger has priority over 186 * the guest. 187 */ 188 for (unsigned iBp = 0; iBp < RT_ELEMENTS(pVM->dbgf.s.aHwBreakpoints); iBp++) 189 { 190 if ( pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.fType == X86_DR7_RW_IO 191 && pVM->dbgf.s.aHwBreakpoints[iBp].fEnabled 192 && pVM->dbgf.s.aHwBreakpoints[iBp].enmType == DBGFBPTYPE_REG ) 193 { 194 uint8_t cbReg = pVM->dbgf.s.aHwBreakpoints[iBp].u.Reg.cb; Assert(RT_IS_POWER_OF_TWO(cbReg)); 195 uint64_t uDrXFirst = pVM->dbgf.s.aHwBreakpoints[iBp].GCPtr & ~(uint64_t)(cbReg - 1); 196 uint64_t uDrXLast = uDrXFirst + cbReg - 1; 197 if (uDrXFirst <= uIoPortLast && uDrXLast >= uIoPortFirst) 198 { 199 /* (See also DBGFRZTrap01Handler.) */ 200 pVCpu->dbgf.s.iActiveBp = pVM->dbgf.s.aHwBreakpoints[iBp].iBp; 201 pVCpu->dbgf.s.fSingleSteppingRaw = false; 202 203 LogFlow(("DBGFBpCheckIo: hit hw breakpoint %d at %04x:%RGv (iop %#x)\n", 204 pVM->dbgf.s.aHwBreakpoints[iBp].iBp, pCtx->cs.Sel, pCtx->rip, uIoPort)); 205 return VINF_EM_DBG_BREAKPOINT; 206 } 207 } 208 } 209 210 /* 211 * Check the guest. 212 */ 213 uint32_t const uDr7 = pCtx->dr[7]; 214 if ( (uDr7 & X86_DR7_ENABLED_MASK) 215 && X86_DR7_ANY_RW_IO(uDr7) 216 && (pCtx->cr4 & X86_CR4_DE) ) 217 { 218 for (unsigned iBp = 0; iBp < 4; iBp++) 219 { 220 if ( (uDr7 & X86_DR7_L_G(iBp)) 221 && X86_DR7_GET_RW(uDr7, iBp) == X86_DR7_RW_IO) 222 { 223 /* ASSUME the breakpoint and the I/O width qualifier uses the same encoding (1 2 x 4). */ 224 static uint8_t const s_abInvAlign[4] = { 0, 1, 7, 3 }; 225 uint8_t cbInvAlign = s_abInvAlign[X86_DR7_GET_LEN(uDr7, iBp)]; 226 uint64_t uDrXFirst = pCtx->dr[iBp] & ~(uint64_t)cbInvAlign; 227 uint64_t uDrXLast = uDrXFirst + cbInvAlign; 228 229 if (uDrXFirst <= uIoPortLast && uDrXLast >= uIoPortFirst) 230 { 231 /* 232 * Update DR6 and DR7. 233 * 234 * See "AMD64 Architecture Programmer's Manual Volume 2", 235 * chapter 13.1.1.3 for details on DR6 bits. The basics is 236 * that the B0..B3 bits are always cleared while the others 237 * must be cleared by software. 238 * 239 * The following section says the GD bit is always cleared 240 * when generating a #DB so the handler can safely access 241 * the debug registers. 242 */ 243 pCtx->dr[6] &= ~X86_DR6_B_MASK; 244 pCtx->dr[6] |= X86_DR6_B(iBp); 245 pCtx->dr[7] &= ~X86_DR7_GD; 246 LogFlow(("DBGFBpCheckIo: hit hw breakpoint %d at %04x:%RGv (iop %#x)\n", 247 pVM->dbgf.s.aHwBreakpoints[iBp].iBp, pCtx->cs.Sel, pCtx->rip, uIoPort)); 248 return VINF_EM_RAW_GUEST_TRAP; 249 } 250 } 251 } 252 } 253 return VINF_SUCCESS; 254 } 255 256 257 /** 133 258 * Returns the single stepping state for a virtual CPU. 134 259 *
Note:
See TracChangeset
for help on using the changeset viewer.