Changeset 47684 in vbox for trunk/src/VBox
- Timestamp:
- Aug 12, 2013 11:45:20 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
r47671 r47684 4069 4069 IoExitInfo.u = (uint32_t)pVmcb->ctrl.u64ExitInfo1; 4070 4070 uint32_t uIOWidth = (IoExitInfo.u >> 4) & 0x7; 4071 uint32_t uIOSize = s_aIOSize[uIOWidth];4071 uint32_t cbValue = s_aIOSize[uIOWidth]; 4072 4072 uint32_t uAndVal = s_aIOOpAnd[uIOWidth]; 4073 4073 4074 if (RT_UNLIKELY(! uIOSize))4074 if (RT_UNLIKELY(!cbValue)) 4075 4075 { 4076 4076 AssertMsgFailed(("hmR0SvmExitIOInstr: Invalid IO operation. uIOWidth=%u\n", uIOWidth)); … … 4078 4078 } 4079 4079 4080 int rc;4080 VBOXSTRICTRC rcStrict; 4081 4081 if (IoExitInfo.n.u1STR) 4082 4082 { … … 4087 4087 * in EXITINFO1? Investigate once this thing is up and running. */ 4088 4088 4089 rc = EMInterpretDisasCurrent(pVM, pVCpu, pDis, NULL);4090 if (rc == VINF_SUCCESS)4089 rcStrict = EMInterpretDisasCurrent(pVM, pVCpu, pDis, NULL); 4090 if (rcStrict == VINF_SUCCESS) 4091 4091 { 4092 4092 if (IoExitInfo.n.u1Type == SVM_IOIO_WRITE) 4093 4093 { 4094 VBOXSTRICTRC rc2 = IOMInterpretOUTSEx(pVM, pVCpu, CPUMCTX2CORE(pCtx), IoExitInfo.n.u16Port, pDis->fPrefix, 4095 (DISCPUMODE)pDis->uAddrMode, uIOSize); 4096 rc = VBOXSTRICTRC_VAL(rc2); 4094 rcStrict = IOMInterpretOUTSEx(pVM, pVCpu, CPUMCTX2CORE(pCtx), IoExitInfo.n.u16Port, pDis->fPrefix, 4095 (DISCPUMODE)pDis->uAddrMode, cbValue); 4097 4096 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOStringWrite); 4098 4097 } 4099 4098 else 4100 4099 { 4101 VBOXSTRICTRC rc2 = IOMInterpretINSEx(pVM, pVCpu, CPUMCTX2CORE(pCtx), IoExitInfo.n.u16Port, pDis->fPrefix, 4102 (DISCPUMODE)pDis->uAddrMode, uIOSize); 4103 rc = VBOXSTRICTRC_VAL(rc2); 4100 rcStrict = IOMInterpretINSEx(pVM, pVCpu, CPUMCTX2CORE(pCtx), IoExitInfo.n.u16Port, pDis->fPrefix, 4101 (DISCPUMODE)pDis->uAddrMode, cbValue); 4104 4102 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOStringRead); 4105 4103 } 4106 4104 } 4107 4105 else 4108 rc = VINF_EM_RAW_EMULATE_INSTR;4106 rcStrict = VINF_EM_RAW_EMULATE_INSTR; 4109 4107 } 4110 4108 else … … 4115 4113 if (IoExitInfo.n.u1Type == SVM_IOIO_WRITE) 4116 4114 { 4117 VBOXSTRICTRC rc2 = IOMIOPortWrite(pVM, pVCpu, IoExitInfo.n.u16Port, pCtx->eax & uAndVal, uIOSize); 4118 rc = VBOXSTRICTRC_VAL(rc2); 4119 if (rc == VINF_IOM_R3_IOPORT_WRITE) 4120 HMR0SavePendingIOPortWrite(pVCpu, pCtx->rip, pVmcb->ctrl.u64ExitInfo2, IoExitInfo.n.u16Port, uAndVal, uIOSize); 4115 rcStrict = IOMIOPortWrite(pVM, pVCpu, IoExitInfo.n.u16Port, pCtx->eax & uAndVal, cbValue); 4116 if (rcStrict == VINF_IOM_R3_IOPORT_WRITE) 4117 HMR0SavePendingIOPortWrite(pVCpu, pCtx->rip, pVmcb->ctrl.u64ExitInfo2, IoExitInfo.n.u16Port, uAndVal, cbValue); 4121 4118 4122 4119 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite); … … 4126 4123 uint32_t u32Val = 0; 4127 4124 4128 VBOXSTRICTRC rc2 = IOMIOPortRead(pVM, pVCpu, IoExitInfo.n.u16Port, &u32Val, uIOSize); 4129 rc = VBOXSTRICTRC_VAL(rc2); 4130 if (IOM_SUCCESS(rc)) 4125 rcStrict = IOMIOPortRead(pVM, pVCpu, IoExitInfo.n.u16Port, &u32Val, cbValue); 4126 if (IOM_SUCCESS(rcStrict)) 4131 4127 { 4132 4128 /* Save result of I/O IN instr. in AL/AX/EAX. */ 4133 4129 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Val & uAndVal); 4134 4130 } 4135 else if (rc == VINF_IOM_R3_IOPORT_READ)4136 HMR0SavePendingIOPortRead(pVCpu, pCtx->rip, pVmcb->ctrl.u64ExitInfo2, IoExitInfo.n.u16Port, uAndVal, uIOSize);4131 else if (rcStrict == VINF_IOM_R3_IOPORT_READ) 4132 HMR0SavePendingIOPortRead(pVCpu, pCtx->rip, pVmcb->ctrl.u64ExitInfo2, IoExitInfo.n.u16Port, uAndVal, cbValue); 4137 4133 4138 4134 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead); … … 4140 4136 } 4141 4137 4142 if (IOM_SUCCESS(rc ))4138 if (IOM_SUCCESS(rcStrict)) 4143 4139 { 4144 4140 /* AMD-V saves the RIP of the instruction following the IO instruction in EXITINFO2. */ 4145 4141 pCtx->rip = pVmcb->ctrl.u64ExitInfo2; 4146 4142 4147 if (RT_LIKELY(rc == VINF_SUCCESS)) 4148 { 4149 /* If any IO breakpoints are armed, then we should check if a debug trap needs to be generated. */ 4150 /** @todo This is inefficient and wrong according to intel and amd specs 4151 * (regardless of which is correct). See the same code in the VT-x case. 4152 * write testcase and refactor the code to use a mostly shared 4153 * implementation after the initial DR7/CR4 checks. */ 4154 if (pCtx->dr[7] & X86_DR7_ENABLED_MASK) 4143 /* 4144 * If any I/O breakpoints are armed, we need to check if one triggered 4145 * and take appropriate action. 4146 * Note that the I/O breakpoint type is undefined if CR4.DE is 0. 4147 */ 4148 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the 4149 * execution engines about whether hyper BPs and such are pending. */ 4150 uint32_t const uDr7 = pCtx->dr[7]; 4151 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK) 4152 && X86_DR7_ANY_RW_IO(uDr7) 4153 && (pCtx->cr4 & X86_CR4_DE)) 4154 || DBGFBpIsHwIoArmed(pVM))) 4155 { 4156 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck); 4157 CPUMR0DebugStateMaybeSaveGuest(pVCpu, false /*fDr6*/); 4158 4159 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, IoExitInfo.n.u16Port, cbValue); 4160 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP) 4155 4161 { 4156 /* I/O breakpoint length, in bytes. */ 4157 static uint32_t const s_aIOBPLen[4] = { 1, 2, 0, 4 }; 4158 4159 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck); 4160 for (unsigned i = 0; i < 4; i++) 4161 { 4162 unsigned uBPLen = s_aIOBPLen[X86_DR7_GET_LEN(pCtx->dr[7], i)]; 4163 4164 if ( IoExitInfo.n.u16Port >= pCtx->dr[i] 4165 && IoExitInfo.n.u16Port < pCtx->dr[i] + uBPLen 4166 && (pCtx->dr[7] & (X86_DR7_L(i) | X86_DR7_G(i))) 4167 && (pCtx->dr[7] & X86_DR7_RW(i, X86_DR7_RW_IO)) == X86_DR7_RW(i, X86_DR7_RW_IO)) 4168 { 4169 Assert(CPUMIsGuestDebugStateActive(pVCpu)); 4170 4171 /* Clear all breakpoint status flags and set the one we just hit. */ 4172 pCtx->dr[6] &= ~(X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3); 4173 pCtx->dr[6] |= (uint64_t)RT_BIT(i); 4174 4175 /* 4176 * Note: AMD64 Architecture Programmer's Manual 13.1: 4177 * Bits 15:13 of the DR6 register is never cleared by the processor and must be cleared 4178 * by software after the contents have been read. 4179 */ 4180 pVmcb->guest.u64DR6 = pCtx->dr[6]; 4181 4182 /* X86_DR7_GD will be cleared if drx accesses should be trapped inside the guest. */ 4183 pCtx->dr[7] &= ~X86_DR7_GD; 4184 4185 /* Paranoia. */ 4186 pCtx->dr[7] &= 0xffffffff; /* Upper 32 bits MBZ. */ 4187 pCtx->dr[7] &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15)); /* MBZ. */ 4188 pCtx->dr[7] |= 0x400; /* MB1. */ 4189 4190 pVmcb->guest.u64DR7 = pCtx->dr[7]; 4191 pVmcb->ctrl.u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_DRX; 4192 4193 /* Inject the debug exception. */ 4194 hmR0SvmSetPendingXcptDB(pVCpu); 4195 break; 4196 } 4197 } 4162 /* Raise #DB. */ 4163 pVmcb->guest.u64DR6 = pCtx->dr[6]; 4164 pVmcb->guest.u64DR7 = pCtx->dr[7]; 4165 pVmcb->ctrl.u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_DRX; 4166 hmR0SvmSetPendingXcptDB(pVCpu); 4198 4167 } 4168 /* rcStrict is VINF_SUCCESS or in [VINF_EM_FIRST..VINF_EM_LAST]. */ 4169 else if ( rcStrict2 != VINF_SUCCESS 4170 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict)) 4171 rcStrict = rcStrict2; 4199 4172 } 4200 4173 } 4201 4174 4202 4175 #ifdef VBOX_STRICT 4203 if (rc == VINF_IOM_R3_IOPORT_READ)4176 if (rcStrict == VINF_IOM_R3_IOPORT_READ) 4204 4177 Assert(IoExitInfo.n.u1Type == SVM_IOIO_READ); 4205 else if (rc == VINF_IOM_R3_IOPORT_WRITE)4178 else if (rcStrict == VINF_IOM_R3_IOPORT_WRITE) 4206 4179 Assert(IoExitInfo.n.u1Type == SVM_IOIO_WRITE); 4207 4180 else 4208 4181 { 4209 AssertMsg( RT_FAILURE(rc) 4210 || rc == VINF_SUCCESS 4211 || rc == VINF_EM_RAW_EMULATE_INSTR 4212 || rc == VINF_EM_RAW_GUEST_TRAP 4213 || rc == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", rc)); 4182 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST 4183 * statuses, that the VMM device and some others may return. See 4184 * IOM_SUCCESS() for guidance. */ 4185 AssertMsg( RT_FAILURE(rcStrict) 4186 || rcStrict == VINF_SUCCESS 4187 || rcStrict == VINF_EM_RAW_EMULATE_INSTR 4188 || rcStrict == VINF_EM_DBG_BREAKPOINT 4189 || rcStrict == VINF_EM_RAW_GUEST_TRAP 4190 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 4214 4191 } 4215 4192 #endif 4216 return rc;4193 return VBOXSTRICTRC_TODO(rcStrict); 4217 4194 } 4218 4195
Note:
See TracChangeset
for help on using the changeset viewer.