Changeset 56072 in vbox for trunk/src/VBox/VMM/VMMRC
- Timestamp:
- May 26, 2015 11:26:35 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMRC/IOMRC.cpp
r45305 r56072 44 44 45 45 /** 46 * IN <AL|AX|EAX>, <DX|imm16> 47 * 48 * @returns Strict VBox status code. Informational status codes other than the one documented 49 * here are to be treated as internal failure. Use IOM_SUCCESS() to check for success. 50 * @retval VINF_SUCCESS Success. 51 * @retval VINF_EM_FIRST-VINF_EM_LAST Success with some exceptions (see IOM_SUCCESS()), the 52 * status code must be passed on to EM. 53 * @retval VINF_IOM_R3_IOPORT_READ Defer the read to ring-3. (R0/GC only) 54 * @retval VINF_EM_RAW_GUEST_TRAP The exception was left pending. (TRPMRaiseXcptErr) 55 * @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr) 56 * @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr) 57 * 58 * @param pVM The virtual machine (GC pointer of course). 59 * @param pVCpu Pointer to the virtual CPU structure of the caller. 60 * @param pRegFrame Pointer to CPUMCTXCORE guest registers structure. 61 * @param pCpu Disassembler CPU state. 62 */ 63 static VBOXSTRICTRC iomRCInterpretIN(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu) 64 { 65 #ifdef IN_RC 66 STAM_COUNTER_INC(&pVM->iom.s.StatInstIn); 67 #endif 68 69 /* 70 * Get port number from second parameter. 71 * And get the register size from the first parameter. 72 */ 73 uint64_t uPort = 0; 74 unsigned cbSize = 0; 75 bool fRc = iomGetRegImmData(pCpu, &pCpu->Param2, pRegFrame, &uPort, &cbSize); 76 AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc); 77 78 cbSize = DISGetParamSize(pCpu, &pCpu->Param1); 79 Assert(cbSize > 0); 80 VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, uPort, cbSize); 81 if (rcStrict == VINF_SUCCESS) 82 { 83 /* 84 * Attempt to read the port. 85 */ 86 uint32_t u32Data = UINT32_C(0xffffffff); 87 rcStrict = IOMIOPortRead(pVM, pVCpu, uPort, &u32Data, cbSize); 88 if (IOM_SUCCESS(rcStrict)) 89 { 90 /* 91 * Store the result in the AL|AX|EAX register. 92 */ 93 fRc = iomSaveDataToReg(pCpu, &pCpu->Param1, pRegFrame, u32Data); 94 AssertMsg(fRc, ("Failed to store register value!\n")); NOREF(fRc); 95 } 96 else 97 AssertMsg(rcStrict == VINF_IOM_R3_IOPORT_READ || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 98 } 99 else 100 AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 101 102 return rcStrict; 103 } 104 105 106 /** 107 * OUT <DX|imm16>, <AL|AX|EAX> 108 * 109 * @returns Strict VBox status code. Informational status codes other than the one documented 110 * here are to be treated as internal failure. Use IOM_SUCCESS() to check for success. 111 * @retval VINF_SUCCESS Success. 112 * @retval VINF_EM_FIRST-VINF_EM_LAST Success with some exceptions (see IOM_SUCCESS()), the 113 * status code must be passed on to EM. 114 * @retval VINF_IOM_R3_IOPORT_WRITE Defer the write to ring-3. (R0/GC only) 115 * @retval VINF_EM_RAW_GUEST_TRAP The exception was left pending. (TRPMRaiseXcptErr) 116 * @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr) 117 * @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr) 118 * 119 * @param pVM The virtual machine (GC pointer of course). 120 * @param pVCpu Pointer to the virtual CPU structure of the caller. 121 * @param pRegFrame Pointer to CPUMCTXCORE guest registers structure. 122 * @param pCpu Disassembler CPU state. 123 */ 124 static VBOXSTRICTRC iomRCInterpretOUT(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu) 125 { 126 #ifdef IN_RC 127 STAM_COUNTER_INC(&pVM->iom.s.StatInstOut); 128 #endif 129 130 /* 131 * Get port number from first parameter. 132 * And get the register size and value from the second parameter. 133 */ 134 uint64_t uPort = 0; 135 unsigned cbSize = 0; 136 bool fRc = iomGetRegImmData(pCpu, &pCpu->Param1, pRegFrame, &uPort, &cbSize); 137 AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc); 138 139 VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, uPort, cbSize); 140 if (rcStrict == VINF_SUCCESS) 141 { 142 uint64_t u64Data = 0; 143 fRc = iomGetRegImmData(pCpu, &pCpu->Param2, pRegFrame, &u64Data, &cbSize); 144 AssertMsg(fRc, ("Failed to get reg value!\n")); NOREF(fRc); 145 146 /* 147 * Attempt to write to the port. 148 */ 149 rcStrict = IOMIOPortWrite(pVM, pVCpu, uPort, u64Data, cbSize); 150 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_IOM_R3_IOPORT_WRITE || (rcStrict >= VINF_EM_FIRST && rcStrict <= VINF_EM_LAST) || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 151 } 152 else 153 AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 154 return rcStrict; 155 } 156 157 158 /** 159 * [REP*] INSB/INSW/INSD 160 * ES:EDI,DX[,ECX] 161 * 162 * @returns Strict VBox status code. Informational status codes other than the one documented 163 * here are to be treated as internal failure. Use IOM_SUCCESS() to check for success. 164 * @retval VINF_SUCCESS Success. 165 * @retval VINF_EM_FIRST-VINF_EM_LAST Success with some exceptions (see IOM_SUCCESS()), the 166 * status code must be passed on to EM. 167 * @retval VINF_IOM_R3_IOPORT_READ Defer the read to ring-3. (R0/GC only) 168 * @retval VINF_EM_RAW_EMULATE_INSTR Defer the read to the REM. 169 * @retval VINF_EM_RAW_GUEST_TRAP The exception was left pending. (TRPMRaiseXcptErr) 170 * @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr) 171 * @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr) 172 * 173 * @param pVM The virtual machine. 174 * @param pVCpu Pointer to the virtual CPU structure of the caller. 175 * @param pRegFrame Pointer to CPUMCTXCORE guest registers structure. 176 * @param pCpu Disassembler CPU state. 177 */ 178 static VBOXSTRICTRC iomRCInterpretINS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu) 179 { 180 /* 181 * Get port number directly from the register (no need to bother the 182 * disassembler). And get the I/O register size from the opcode / prefix. 183 */ 184 RTIOPORT Port = pRegFrame->edx & 0xffff; 185 unsigned cb; 186 if (pCpu->pCurInstr->uOpcode == OP_INSB) 187 cb = 1; 188 else 189 cb = (pCpu->uOpMode == DISCPUMODE_16BIT) ? 2 : 4; /* dword in both 32 & 64 bits mode */ 190 191 VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, Port, cb); 192 if (RT_UNLIKELY(rcStrict != VINF_SUCCESS)) 193 { 194 AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 195 return rcStrict; 196 } 197 198 return IOMInterpretINSEx(pVM, pVCpu, pRegFrame, Port, pCpu->fPrefix, (DISCPUMODE)pCpu->uAddrMode, cb); 199 } 200 201 202 /** 203 * [REP*] OUTSB/OUTSW/OUTSD 204 * DS:ESI,DX[,ECX] 205 * 206 * @returns Strict VBox status code. Informational status codes other than the one documented 207 * here are to be treated as internal failure. Use IOM_SUCCESS() to check for success. 208 * @retval VINF_SUCCESS Success. 209 * @retval VINF_EM_FIRST-VINF_EM_LAST Success with some exceptions (see IOM_SUCCESS()), the 210 * status code must be passed on to EM. 211 * @retval VINF_IOM_R3_IOPORT_WRITE Defer the write to ring-3. (R0/GC only) 212 * @retval VINF_EM_RAW_EMULATE_INSTR Defer the write to the REM. 213 * @retval VINF_EM_RAW_GUEST_TRAP The exception was left pending. (TRPMRaiseXcptErr) 214 * @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr) 215 * @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr) 216 * 217 * @param pVM The virtual machine. 218 * @param pVCpu Pointer to the virtual CPU structure of the caller. 219 * @param pRegFrame Pointer to CPUMCTXCORE guest registers structure. 220 * @param pCpu Disassembler CPU state. 221 */ 222 static VBOXSTRICTRC iomRCInterpretOUTS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu) 223 { 224 /* 225 * Get port number from the first parameter. 226 * And get the I/O register size from the opcode / prefix. 227 */ 228 uint64_t Port = 0; 229 unsigned cb; 230 bool fRc = iomGetRegImmData(pCpu, &pCpu->Param1, pRegFrame, &Port, &cb); 231 AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc); 232 if (pCpu->pCurInstr->uOpcode == OP_OUTSB) 233 cb = 1; 234 else 235 cb = (pCpu->uOpMode == DISCPUMODE_16BIT) ? 2 : 4; /* dword in both 32 & 64 bits mode */ 236 237 VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, Port, cb); 238 if (RT_UNLIKELY(rcStrict != VINF_SUCCESS)) 239 { 240 AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); 241 return rcStrict; 242 } 243 244 return IOMInterpretOUTSEx(pVM, pVCpu, pRegFrame, Port, pCpu->fPrefix, (DISCPUMODE)pCpu->uAddrMode, cb); 245 } 246 247 248 249 /** 46 250 * Attempts to service an IN/OUT instruction. 47 251 * … … 71 275 { 72 276 case OP_IN: 73 return IOMInterpretIN(pVM, pVCpu, pRegFrame, pCpu);277 return iomRCInterpretIN(pVM, pVCpu, pRegFrame, pCpu); 74 278 75 279 case OP_OUT: 76 return IOMInterpretOUT(pVM, pVCpu, pRegFrame, pCpu);280 return iomRCInterpretOUT(pVM, pVCpu, pRegFrame, pCpu); 77 281 78 282 case OP_INSB: 79 283 case OP_INSWD: 80 return IOMInterpretINS(pVM, pVCpu, pRegFrame, pCpu);284 return iomRCInterpretINS(pVM, pVCpu, pRegFrame, pCpu); 81 285 82 286 case OP_OUTSB: 83 287 case OP_OUTSWD: 84 return IOMInterpretOUTS(pVM, pVCpu, pRegFrame, pCpu);288 return iomRCInterpretOUTS(pVM, pVCpu, pRegFrame, pCpu); 85 289 86 290 /*
Note:
See TracChangeset
for help on using the changeset viewer.