- Timestamp:
- Jun 14, 2013 1:41:37 PM (12 years ago)
- Location:
- trunk/src/VBox/VMM/VMMR0
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
r46557 r46562 2747 2747 * 2748 2748 * @return VBox status code. 2749 * @param pVCpu hmR0SvmExitReadDRxPointer to the VMCPU.2749 * @param pVCpu Pointer to the VMCPU. 2750 2750 * @param pCpu Pointer to the disassembler state. 2751 2751 * @param pRegFrame Pointer to the register frame. … … 2823 2823 SVMEVENT Event; 2824 2824 Event.u = 0; 2825 Event.n.u1Valid = 1; 2825 2826 Event.n.u3Type = SVM_EVENT_EXCEPTION; 2827 Event.n.u8Vector = X86_XCPT_UD; 2828 hmR0SvmSetPendingEvent(pVCpu, &Event); 2829 } 2830 2831 2832 /** 2833 * Sets an debug (#DB) exception as pending-for-injection into the VM. 2834 * 2835 * @param pVCpu Pointer to the VMCPU. 2836 */ 2837 DECLINLINE(void) hmR0SvmSetPendingXcptDB(PVMCPU pVCpu) 2838 { 2839 SVMEVENT Event; 2840 Event.u = 0; 2826 2841 Event.n.u1Valid = 1; 2827 Event.n.u8Vector = X86_XCPT_UD; 2842 Event.n.u3Type = SVM_EVENT_EXCEPTION; 2843 Event.n.u8Vector = X86_XCPT_DB; 2828 2844 hmR0SvmSetPendingEvent(pVCpu, &Event); 2829 2845 } … … 3208 3224 HMSVM_EXIT_DECL hmR0SvmExitWriteDRx(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMTRANSIENT pSvmTransient) 3209 3225 { 3226 HMSVM_VALIDATE_EXIT_HANDLER_PARAMS(); 3210 3227 /* For now it's the same since we interpret the instruction anyway. Will change when using of Decode Assist is implemented. */ 3211 3228 int rc = hmR0SvmExitReadDRx(pVCpu, pCtx, pSvmTransient); … … 3216 3233 3217 3234 3235 /** 3236 * #VMEXIT handler for I/O instructions (SVM_EXIT_IOIO). Conditional #VMEXIT. 3237 */ 3238 HMSVM_EXIT_DECL hmR0SvmExitIOInstr(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMTRANSIENT pSvmTransient) 3239 { 3240 HMSVM_VALIDATE_EXIT_HANDLER_PARAMS(); 3241 3242 /* I/O operation lookup arrays. */ 3243 static uint32_t const s_aIOSize[8] = { 0, 1, 2, 0, 4, 0, 0, 0 }; /* Size of the I/O accesses in bytes. */ 3244 static uint32_t const s_aIOOpAnd[8] = { 0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0 }; /* AND masks for saving 3245 the result (in AL/AX/EAX). */ 3246 3247 /* Refer AMD spec. 15.10.2 "IN and OUT Behaviour" and Figure 15-2. "EXITINFO1 for IOIO Intercept" for the format. */ 3248 SVMIOIOEXIT IoExitInfo; 3249 IoExitInfo.u = (uint32_t)pVmcb->ctrl.u64ExitInfo1; 3250 uint32_t uIOWidth = (IoExitInfo.u >> 4) & 0x7; 3251 uint32_t uIOSize = s_aIOSize[uIOWidth]; 3252 uint32_t uAndVal = s_aIOOpAnd[uIOWidth]; 3253 3254 if (RT_UNLIKELY(!uIOSize)) 3255 { 3256 AssertMsgFailed(("hmR0SvmExitIOInstr: Invalid IO operation. uIOWidth=%u\n", uIOWidth)); 3257 return VERR_EM_INTERPRETER; 3258 } 3259 3260 int rc; 3261 if (IoExitInfo.n.u1STR) 3262 { 3263 /* INS/OUTS - I/O String instruction. */ 3264 PDISCPUSTATE pDis = &pVCpu->hm.s.DisState; 3265 3266 /** @todo Huh? why can't we use the segment prefix information given by AMD-V 3267 * in EXITINFO1? Investigate once this thing is up and running. */ 3268 3269 rc = EMInterpretDisasCurrent(pVM, pVCpu, pDis, NULL); 3270 if (rc == VINF_SUCCESS) 3271 { 3272 if (IoExitInfo.n.u1Type == 0) /* OUT */ 3273 { 3274 rc = IOMInterpretOUTSEx(pVM, pVCpu, CPUMCTX2CORE(pCtx), IoExitInfo.n.u16Port, pDis->fPrefix, 3275 (DISCPUMODE)pDis->uAddrMode, uIOSize); 3276 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOStringWrite); 3277 } 3278 else 3279 { 3280 rc = IOMInterpretINSEx(pVM, pVCpu, CPUMCTX2CORE(pCtx), IoExitInfo.n.u16Port, pDis->fPrefix, 3281 (DISCPUMODE)pDis->uAddrMode, uIOSize); 3282 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOStringRead); 3283 } 3284 } 3285 else 3286 rc = VINF_EM_RAW_EMULATE_INSTR; 3287 } 3288 else 3289 { 3290 /* IN/OUT - I/O instruction. */ 3291 Assert(!IoExitInfo.n.u1REP); 3292 3293 if (IoExitInfo.n.u1Type == 0) /* OUT */ 3294 { 3295 rc = IOMIOPortWrite(pVM, pVCpu, IoExitInfo.n.u16Port, pCtx->eax & uAndVal, uIOSize); 3296 if (rc == VINF_IOM_R3_IOPORT_WRITE) 3297 HMR0SavePendingIOPortWrite(pVCpu, pCtx->rip, pVmcb->ctrl.u64ExitInfo2, IoExitInfo.n.u16Port, uAndVal, uIOSize); 3298 3299 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite); 3300 } 3301 else 3302 { 3303 uint32_t u32Val = 0; 3304 3305 rc = IOMIOPortRead(pVM, pVCpu, IoExitInfo.n.u16Port, &u32Val, uIOSize); 3306 if (IOM_SUCCESS(rc)) 3307 { 3308 /* Save result of I/O IN instr. in AL/AX/EAX. */ 3309 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Val & uAndVal); 3310 } 3311 else if (rc == VINF_IOM_R3_IOPORT_READ) 3312 HMR0SavePendingIOPortRead(pVCpu, pCtx->rip, pVmcb->ctrl.u64ExitInfo2, IoExitInfo.n.u16Port, uAndVal, uIOSize); 3313 3314 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead); 3315 } 3316 } 3317 3318 if (IOM_SUCCESS(rc)) 3319 { 3320 /* AMD-V saves the RIP of the instruction following the IO instruction in EXITINFO2. */ 3321 pCtx->rip = pVmcb->ctrl.u64ExitInfo2; 3322 3323 if (RT_LIKELY(rc == VINF_SUCCESS)) 3324 { 3325 /* If any IO breakpoints are armed, then we should check if a debug trap needs to be generated. */ 3326 if (pCtx->dr[7] & X86_DR7_ENABLED_MASK) 3327 { 3328 /* I/O breakpoint length, in bytes. */ 3329 static uint32_t const s_aIOBPLen[4] = { 1, 2, 0, 4 }; 3330 3331 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck); 3332 for (unsigned i = 0; i < 4; i++) 3333 { 3334 unsigned uBPLen = s_aIOBPLen[X86_DR7_GET_LEN(pCtx->dr[7], i)]; 3335 3336 if ( IoExitInfo.n.u16Port >= pCtx->dr[i] 3337 && IoExitInfo.n.u16Port < pCtx->dr[i] + uBPLen 3338 && (pCtx->dr[7] & (X86_DR7_L(i) | X86_DR7_G(i))) 3339 && (pCtx->dr[7] & X86_DR7_RW(i, X86_DR7_RW_IO)) == X86_DR7_RW(i, X86_DR7_RW_IO)) 3340 { 3341 Assert(CPUMIsGuestDebugStateActive(pVCpu)); 3342 3343 /* Clear all breakpoint status flags and set the one we just hit. */ 3344 pCtx->dr[6] &= ~(X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3); 3345 pCtx->dr[6] |= (uint64_t)RT_BIT(i); 3346 3347 /* 3348 * Note: AMD64 Architecture Programmer's Manual 13.1: 3349 * Bits 15:13 of the DR6 register is never cleared by the processor and must be cleared 3350 * by software after the contents have been read. 3351 */ 3352 pVmcb->guest.u64DR6 = pCtx->dr[6]; 3353 3354 /* X86_DR7_GD will be cleared if drx accesses should be trapped inside the guest. */ 3355 pCtx->dr[7] &= ~X86_DR7_GD; 3356 3357 /* Paranoia. */ 3358 pMixedCtx->dr[7] &= 0xffffffff; /* Upper 32 bits MBZ. */ 3359 pMixedCtx->dr[7] &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15)); /* MBZ. */ 3360 pMixedCtx->dr[7] |= 0x400; /* MB1. */ 3361 3362 pVmcb->guest.u64DR7 = pCtx->dr[7]; 3363 pVmcb->ctrl.u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_DRX; 3364 3365 /* Inject the debug exception. */ 3366 hmR0SvmSetPendingXcptDB(pVCpu); 3367 break; 3368 } 3369 } 3370 } 3371 } 3372 } 3373 3374 #ifdef DEBUG 3375 if (rc == VINF_IOM_R3_IOPORT_READ) 3376 Assert(IoExitInfo.n.u1Type != 0); 3377 else if (rc == VINF_IOM_R3_IOPORT_WRITE) 3378 Assert(IoExitInfo.n.u1Type == 0); 3379 else 3380 { 3381 AssertMsg( RT_FAILURE(rc) 3382 || rc == VINF_SUCCESS 3383 || rc == VINF_EM_RAW_EMULATE_INSTR 3384 || rc == VINF_EM_RAW_GUEST_TRAP 3385 || rc == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", rc)); 3386 } 3387 #endif 3388 return rc; 3389 } 3390 -
trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
r46552 r46562 8219 8219 8220 8220 /* I/O operation lookup arrays. */ 8221 static const uint32_t s_aIOSize[4] = { 1, 2, 0, 4 }; /* Size of the I/O Accesses. */8221 static const uint32_t s_aIOSize[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses. */ 8222 8222 static const uint32_t s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving the result (in AL/AX/EAX). */ 8223 8223
Note:
See TracChangeset
for help on using the changeset viewer.