Changeset 56072 in vbox
- Timestamp:
- May 26, 2015 11:26:35 AM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 100594
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/iom.h
r53615 r56072 271 271 VMMDECL(VBOXSTRICTRC) IOMIOPortRead(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue); 272 272 VMMDECL(VBOXSTRICTRC) IOMIOPortWrite(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, uint32_t u32Value, size_t cbValue); 273 VMMDECL(VBOXSTRICTRC) IOMInterpretOUT(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);274 VMMDECL(VBOXSTRICTRC) IOMInterpretIN(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);275 273 VMMDECL(VBOXSTRICTRC) IOMIOPortReadString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, PRTGCPTR pGCPtrDst, PRTGCUINTREG pcTransfers, unsigned cb); 276 274 VMMDECL(VBOXSTRICTRC) IOMIOPortWriteString(PVM pVM, PVMCPU pVCpu, RTIOPORT Port, PRTGCPTR pGCPtrSrc, PRTGCUINTREG pcTransfers, unsigned cb); 277 VMMDECL(VBOXSTRICTRC) IOMInterpretINS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);278 275 VMMDECL(VBOXSTRICTRC) IOMInterpretINSEx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer); 279 VMMDECL(VBOXSTRICTRC) IOMInterpretOUTS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);280 276 VMMDECL(VBOXSTRICTRC) IOMInterpretOUTSEx(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer); 281 277 VMMDECL(VBOXSTRICTRC) IOMMMIORead(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, uint32_t *pu32Value, size_t cbValue); -
trunk/src/VBox/VMM/VMMAll/IOMAll.cpp
r55816 r56072 57 57 58 58 59 /**60 * Returns the contents of register or immediate data of instruction's parameter.61 *62 * @returns true on success.63 *64 * @todo Get rid of this code. Use DISQueryParamVal instead65 *66 * @param pCpu Pointer to current disassembler context.67 * @param pParam Pointer to parameter of instruction to process.68 * @param pRegFrame Pointer to CPUMCTXCORE guest structure.69 * @param pu64Data Where to store retrieved data.70 * @param pcbSize Where to store the size of data (1, 2, 4, 8).71 */72 bool iomGetRegImmData(PDISCPUSTATE pCpu, PCDISOPPARAM pParam, PCPUMCTXCORE pRegFrame, uint64_t *pu64Data, unsigned *pcbSize)73 {74 NOREF(pCpu);75 if (pParam->fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_SCALE | DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32))76 {77 *pcbSize = 0;78 *pu64Data = 0;79 return false;80 }81 82 /* divide and conquer */83 if (pParam->fUse & (DISUSE_REG_GEN64 | DISUSE_REG_GEN32 | DISUSE_REG_GEN16 | DISUSE_REG_GEN8))84 {85 if (pParam->fUse & DISUSE_REG_GEN32)86 {87 *pcbSize = 4;88 DISFetchReg32(pRegFrame, pParam->Base.idxGenReg, (uint32_t *)pu64Data);89 return true;90 }91 92 if (pParam->fUse & DISUSE_REG_GEN16)93 {94 *pcbSize = 2;95 DISFetchReg16(pRegFrame, pParam->Base.idxGenReg, (uint16_t *)pu64Data);96 return true;97 }98 99 if (pParam->fUse & DISUSE_REG_GEN8)100 {101 *pcbSize = 1;102 DISFetchReg8(pRegFrame, pParam->Base.idxGenReg, (uint8_t *)pu64Data);103 return true;104 }105 106 Assert(pParam->fUse & DISUSE_REG_GEN64);107 *pcbSize = 8;108 DISFetchReg64(pRegFrame, pParam->Base.idxGenReg, pu64Data);109 return true;110 }111 else112 {113 if (pParam->fUse & (DISUSE_IMMEDIATE64 | DISUSE_IMMEDIATE64_SX8))114 {115 *pcbSize = 8;116 *pu64Data = pParam->uValue;117 return true;118 }119 120 if (pParam->fUse & (DISUSE_IMMEDIATE32 | DISUSE_IMMEDIATE32_SX8))121 {122 *pcbSize = 4;123 *pu64Data = (uint32_t)pParam->uValue;124 return true;125 }126 127 if (pParam->fUse & (DISUSE_IMMEDIATE16 | DISUSE_IMMEDIATE16_SX8))128 {129 *pcbSize = 2;130 *pu64Data = (uint16_t)pParam->uValue;131 return true;132 }133 134 if (pParam->fUse & DISUSE_IMMEDIATE8)135 {136 *pcbSize = 1;137 *pu64Data = (uint8_t)pParam->uValue;138 return true;139 }140 141 if (pParam->fUse & DISUSE_REG_SEG)142 {143 *pcbSize = 2;144 DISFetchRegSeg(pRegFrame, (DISSELREG)pParam->Base.idxSegReg, (RTSEL *)pu64Data);145 return true;146 } /* Else - error. */147 148 AssertFailed();149 *pcbSize = 0;150 *pu64Data = 0;151 return false;152 }153 }154 155 156 /**157 * Saves data to 8/16/32 general purpose or segment register defined by158 * instruction's parameter.159 *160 * @returns true on success.161 * @param pCpu Pointer to current disassembler context.162 * @param pParam Pointer to parameter of instruction to process.163 * @param pRegFrame Pointer to CPUMCTXCORE guest structure.164 * @param u64Data 8/16/32/64 bit data to store.165 */166 bool iomSaveDataToReg(PDISCPUSTATE pCpu, PCDISOPPARAM pParam, PCPUMCTXCORE pRegFrame, uint64_t u64Data)167 {168 NOREF(pCpu);169 if (pParam->fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_SCALE | DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT64 | DISUSE_IMMEDIATE8 | DISUSE_IMMEDIATE16 | DISUSE_IMMEDIATE32 | DISUSE_IMMEDIATE32_SX8 | DISUSE_IMMEDIATE16_SX8))170 {171 return false;172 }173 174 if (pParam->fUse & DISUSE_REG_GEN32)175 {176 DISWriteReg32(pRegFrame, pParam->Base.idxGenReg, (uint32_t)u64Data);177 return true;178 }179 180 if (pParam->fUse & DISUSE_REG_GEN64)181 {182 DISWriteReg64(pRegFrame, pParam->Base.idxGenReg, u64Data);183 return true;184 }185 186 if (pParam->fUse & DISUSE_REG_GEN16)187 {188 DISWriteReg16(pRegFrame, pParam->Base.idxGenReg, (uint16_t)u64Data);189 return true;190 }191 192 if (pParam->fUse & DISUSE_REG_GEN8)193 {194 DISWriteReg8(pRegFrame, pParam->Base.idxGenReg, (uint8_t)u64Data);195 return true;196 }197 198 if (pParam->fUse & DISUSE_REG_SEG)199 {200 DISWriteRegSeg(pRegFrame, (DISSELREG)pParam->Base.idxSegReg, (RTSEL)u64Data);201 return true;202 }203 204 /* Else - error. */205 return false;206 }207 208 209 59 //#undef LOG_GROUP 210 60 //#define LOG_GROUP LOG_GROUP_IOM_IOPORT … … 893 743 894 744 /** 895 * IN <AL|AX|EAX>, <DX|imm16>896 *897 * @returns Strict VBox status code. Informational status codes other than the one documented898 * here are to be treated as internal failure. Use IOM_SUCCESS() to check for success.899 * @retval VINF_SUCCESS Success.900 * @retval VINF_EM_FIRST-VINF_EM_LAST Success with some exceptions (see IOM_SUCCESS()), the901 * status code must be passed on to EM.902 * @retval VINF_IOM_R3_IOPORT_READ Defer the read to ring-3. (R0/GC only)903 * @retval VINF_EM_RAW_GUEST_TRAP The exception was left pending. (TRPMRaiseXcptErr)904 * @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)905 * @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)906 *907 * @param pVM The virtual machine (GC pointer of course).908 * @param pVCpu Pointer to the virtual CPU structure of the caller.909 * @param pRegFrame Pointer to CPUMCTXCORE guest registers structure.910 * @param pCpu Disassembler CPU state.911 */912 VMMDECL(VBOXSTRICTRC) IOMInterpretIN(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)913 {914 #ifdef IN_RC915 STAM_COUNTER_INC(&pVM->iom.s.StatInstIn);916 #endif917 918 /*919 * Get port number from second parameter.920 * And get the register size from the first parameter.921 */922 uint64_t uPort = 0;923 unsigned cbSize = 0;924 bool fRc = iomGetRegImmData(pCpu, &pCpu->Param2, pRegFrame, &uPort, &cbSize);925 AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);926 927 cbSize = DISGetParamSize(pCpu, &pCpu->Param1);928 Assert(cbSize > 0);929 VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, uPort, cbSize);930 if (rcStrict == VINF_SUCCESS)931 {932 /*933 * Attempt to read the port.934 */935 uint32_t u32Data = UINT32_C(0xffffffff);936 rcStrict = IOMIOPortRead(pVM, pVCpu, uPort, &u32Data, cbSize);937 if (IOM_SUCCESS(rcStrict))938 {939 /*940 * Store the result in the AL|AX|EAX register.941 */942 fRc = iomSaveDataToReg(pCpu, &pCpu->Param1, pRegFrame, u32Data);943 AssertMsg(fRc, ("Failed to store register value!\n")); NOREF(fRc);944 }945 else946 AssertMsg(rcStrict == VINF_IOM_R3_IOPORT_READ || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));947 }948 else949 AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));950 951 return rcStrict;952 }953 954 955 /**956 * OUT <DX|imm16>, <AL|AX|EAX>957 *958 * @returns Strict VBox status code. Informational status codes other than the one documented959 * here are to be treated as internal failure. Use IOM_SUCCESS() to check for success.960 * @retval VINF_SUCCESS Success.961 * @retval VINF_EM_FIRST-VINF_EM_LAST Success with some exceptions (see IOM_SUCCESS()), the962 * status code must be passed on to EM.963 * @retval VINF_IOM_R3_IOPORT_WRITE Defer the write to ring-3. (R0/GC only)964 * @retval VINF_EM_RAW_GUEST_TRAP The exception was left pending. (TRPMRaiseXcptErr)965 * @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)966 * @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)967 *968 * @param pVM The virtual machine (GC pointer of course).969 * @param pVCpu Pointer to the virtual CPU structure of the caller.970 * @param pRegFrame Pointer to CPUMCTXCORE guest registers structure.971 * @param pCpu Disassembler CPU state.972 */973 VMMDECL(VBOXSTRICTRC) IOMInterpretOUT(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)974 {975 #ifdef IN_RC976 STAM_COUNTER_INC(&pVM->iom.s.StatInstOut);977 #endif978 979 /*980 * Get port number from first parameter.981 * And get the register size and value from the second parameter.982 */983 uint64_t uPort = 0;984 unsigned cbSize = 0;985 bool fRc = iomGetRegImmData(pCpu, &pCpu->Param1, pRegFrame, &uPort, &cbSize);986 AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);987 988 VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, uPort, cbSize);989 if (rcStrict == VINF_SUCCESS)990 {991 uint64_t u64Data = 0;992 fRc = iomGetRegImmData(pCpu, &pCpu->Param2, pRegFrame, &u64Data, &cbSize);993 AssertMsg(fRc, ("Failed to get reg value!\n")); NOREF(fRc);994 995 /*996 * Attempt to write to the port.997 */998 rcStrict = IOMIOPortWrite(pVM, pVCpu, uPort, u64Data, cbSize);999 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)));1000 }1001 else1002 AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));1003 return rcStrict;1004 }1005 1006 1007 /**1008 745 * Fress an MMIO range after the reference counter has become zero. 1009 746 * -
trunk/src/VBox/VMM/VMMAll/IOMAllMMIO.cpp
r56064 r56072 74 74 */ 75 75 #define SIZE_2_SHIFT(cb) (g_aSize2Shift[cb]) 76 77 78 /** 79 * Returns the contents of register or immediate data of instruction's parameter. 80 * 81 * @returns true on success. 82 * 83 * @todo Get rid of this code. Use DISQueryParamVal instead 84 * 85 * @param pCpu Pointer to current disassembler context. 86 * @param pParam Pointer to parameter of instruction to process. 87 * @param pRegFrame Pointer to CPUMCTXCORE guest structure. 88 * @param pu64Data Where to store retrieved data. 89 * @param pcbSize Where to store the size of data (1, 2, 4, 8). 90 */ 91 bool iomGetRegImmData(PDISCPUSTATE pCpu, PCDISOPPARAM pParam, PCPUMCTXCORE pRegFrame, uint64_t *pu64Data, unsigned *pcbSize) 92 { 93 NOREF(pCpu); 94 if (pParam->fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_SCALE | DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32)) 95 { 96 *pcbSize = 0; 97 *pu64Data = 0; 98 return false; 99 } 100 101 /* divide and conquer */ 102 if (pParam->fUse & (DISUSE_REG_GEN64 | DISUSE_REG_GEN32 | DISUSE_REG_GEN16 | DISUSE_REG_GEN8)) 103 { 104 if (pParam->fUse & DISUSE_REG_GEN32) 105 { 106 *pcbSize = 4; 107 DISFetchReg32(pRegFrame, pParam->Base.idxGenReg, (uint32_t *)pu64Data); 108 return true; 109 } 110 111 if (pParam->fUse & DISUSE_REG_GEN16) 112 { 113 *pcbSize = 2; 114 DISFetchReg16(pRegFrame, pParam->Base.idxGenReg, (uint16_t *)pu64Data); 115 return true; 116 } 117 118 if (pParam->fUse & DISUSE_REG_GEN8) 119 { 120 *pcbSize = 1; 121 DISFetchReg8(pRegFrame, pParam->Base.idxGenReg, (uint8_t *)pu64Data); 122 return true; 123 } 124 125 Assert(pParam->fUse & DISUSE_REG_GEN64); 126 *pcbSize = 8; 127 DISFetchReg64(pRegFrame, pParam->Base.idxGenReg, pu64Data); 128 return true; 129 } 130 else 131 { 132 if (pParam->fUse & (DISUSE_IMMEDIATE64 | DISUSE_IMMEDIATE64_SX8)) 133 { 134 *pcbSize = 8; 135 *pu64Data = pParam->uValue; 136 return true; 137 } 138 139 if (pParam->fUse & (DISUSE_IMMEDIATE32 | DISUSE_IMMEDIATE32_SX8)) 140 { 141 *pcbSize = 4; 142 *pu64Data = (uint32_t)pParam->uValue; 143 return true; 144 } 145 146 if (pParam->fUse & (DISUSE_IMMEDIATE16 | DISUSE_IMMEDIATE16_SX8)) 147 { 148 *pcbSize = 2; 149 *pu64Data = (uint16_t)pParam->uValue; 150 return true; 151 } 152 153 if (pParam->fUse & DISUSE_IMMEDIATE8) 154 { 155 *pcbSize = 1; 156 *pu64Data = (uint8_t)pParam->uValue; 157 return true; 158 } 159 160 if (pParam->fUse & DISUSE_REG_SEG) 161 { 162 *pcbSize = 2; 163 DISFetchRegSeg(pRegFrame, (DISSELREG)pParam->Base.idxSegReg, (RTSEL *)pu64Data); 164 return true; 165 } /* Else - error. */ 166 167 AssertFailed(); 168 *pcbSize = 0; 169 *pu64Data = 0; 170 return false; 171 } 172 } 173 174 175 /** 176 * Saves data to 8/16/32 general purpose or segment register defined by 177 * instruction's parameter. 178 * 179 * @returns true on success. 180 * @param pCpu Pointer to current disassembler context. 181 * @param pParam Pointer to parameter of instruction to process. 182 * @param pRegFrame Pointer to CPUMCTXCORE guest structure. 183 * @param u64Data 8/16/32/64 bit data to store. 184 */ 185 bool iomSaveDataToReg(PDISCPUSTATE pCpu, PCDISOPPARAM pParam, PCPUMCTXCORE pRegFrame, uint64_t u64Data) 186 { 187 NOREF(pCpu); 188 if (pParam->fUse & (DISUSE_BASE | DISUSE_INDEX | DISUSE_SCALE | DISUSE_DISPLACEMENT8 | DISUSE_DISPLACEMENT16 | DISUSE_DISPLACEMENT32 | DISUSE_DISPLACEMENT64 | DISUSE_IMMEDIATE8 | DISUSE_IMMEDIATE16 | DISUSE_IMMEDIATE32 | DISUSE_IMMEDIATE32_SX8 | DISUSE_IMMEDIATE16_SX8)) 189 { 190 return false; 191 } 192 193 if (pParam->fUse & DISUSE_REG_GEN32) 194 { 195 DISWriteReg32(pRegFrame, pParam->Base.idxGenReg, (uint32_t)u64Data); 196 return true; 197 } 198 199 if (pParam->fUse & DISUSE_REG_GEN64) 200 { 201 DISWriteReg64(pRegFrame, pParam->Base.idxGenReg, u64Data); 202 return true; 203 } 204 205 if (pParam->fUse & DISUSE_REG_GEN16) 206 { 207 DISWriteReg16(pRegFrame, pParam->Base.idxGenReg, (uint16_t)u64Data); 208 return true; 209 } 210 211 if (pParam->fUse & DISUSE_REG_GEN8) 212 { 213 DISWriteReg8(pRegFrame, pParam->Base.idxGenReg, (uint8_t)u64Data); 214 return true; 215 } 216 217 if (pParam->fUse & DISUSE_REG_SEG) 218 { 219 DISWriteRegSeg(pRegFrame, (DISSELREG)pParam->Base.idxSegReg, (RTSEL)u64Data); 220 return true; 221 } 222 223 /* Else - error. */ 224 return false; 225 } 76 226 77 227 … … 2231 2381 2232 2382 2233 #ifdef IN_RC /* Latter for IOMRCIOPortHandler */2234 /**2235 * [REP*] INSB/INSW/INSD2236 * ES:EDI,DX[,ECX]2237 *2238 * @returns Strict VBox status code. Informational status codes other than the one documented2239 * here are to be treated as internal failure. Use IOM_SUCCESS() to check for success.2240 * @retval VINF_SUCCESS Success.2241 * @retval VINF_EM_FIRST-VINF_EM_LAST Success with some exceptions (see IOM_SUCCESS()), the2242 * status code must be passed on to EM.2243 * @retval VINF_IOM_R3_IOPORT_READ Defer the read to ring-3. (R0/GC only)2244 * @retval VINF_EM_RAW_EMULATE_INSTR Defer the read to the REM.2245 * @retval VINF_EM_RAW_GUEST_TRAP The exception was left pending. (TRPMRaiseXcptErr)2246 * @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)2247 * @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)2248 *2249 * @param pVM The virtual machine.2250 * @param pVCpu Pointer to the virtual CPU structure of the caller.2251 * @param pRegFrame Pointer to CPUMCTXCORE guest registers structure.2252 * @param pCpu Disassembler CPU state.2253 */2254 VMMDECL(VBOXSTRICTRC) IOMInterpretINS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)2255 {2256 /*2257 * Get port number directly from the register (no need to bother the2258 * disassembler). And get the I/O register size from the opcode / prefix.2259 */2260 RTIOPORT Port = pRegFrame->edx & 0xffff;2261 unsigned cb = 0;2262 if (pCpu->pCurInstr->uOpcode == OP_INSB)2263 cb = 1;2264 else2265 cb = (pCpu->uOpMode == DISCPUMODE_16BIT) ? 2 : 4; /* dword in both 32 & 64 bits mode */2266 2267 VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, Port, cb);2268 if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))2269 {2270 AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));2271 return rcStrict;2272 }2273 2274 return IOMInterpretINSEx(pVM, pVCpu, pRegFrame, Port, pCpu->fPrefix, (DISCPUMODE)pCpu->uAddrMode, cb);2275 }2276 #endif /* RC */2277 2278 2279 2383 /** 2280 2384 * [REP*] OUTSB/OUTSW/OUTSD … … 2399 2503 } 2400 2504 2401 2402 #ifdef IN_RC /* Latter for IOMRCIOPortHandler */2403 /**2404 * [REP*] OUTSB/OUTSW/OUTSD2405 * DS:ESI,DX[,ECX]2406 *2407 * @returns Strict VBox status code. Informational status codes other than the one documented2408 * here are to be treated as internal failure. Use IOM_SUCCESS() to check for success.2409 * @retval VINF_SUCCESS Success.2410 * @retval VINF_EM_FIRST-VINF_EM_LAST Success with some exceptions (see IOM_SUCCESS()), the2411 * status code must be passed on to EM.2412 * @retval VINF_IOM_R3_IOPORT_WRITE Defer the write to ring-3. (R0/GC only)2413 * @retval VINF_EM_RAW_EMULATE_INSTR Defer the write to the REM.2414 * @retval VINF_EM_RAW_GUEST_TRAP The exception was left pending. (TRPMRaiseXcptErr)2415 * @retval VINF_TRPM_XCPT_DISPATCHED The exception was raised and dispatched for raw-mode execution. (TRPMRaiseXcptErr)2416 * @retval VINF_EM_RESCHEDULE_REM The exception was dispatched and cannot be executed in raw-mode. (TRPMRaiseXcptErr)2417 *2418 * @param pVM The virtual machine.2419 * @param pVCpu Pointer to the virtual CPU structure of the caller.2420 * @param pRegFrame Pointer to CPUMCTXCORE guest registers structure.2421 * @param pCpu Disassembler CPU state.2422 */2423 VMMDECL(VBOXSTRICTRC) IOMInterpretOUTS(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu)2424 {2425 /*2426 * Get port number from the first parameter.2427 * And get the I/O register size from the opcode / prefix.2428 */2429 uint64_t Port = 0;2430 unsigned cb = 0;2431 bool fRc = iomGetRegImmData(pCpu, &pCpu->Param1, pRegFrame, &Port, &cb);2432 AssertMsg(fRc, ("Failed to get reg/imm port number!\n")); NOREF(fRc);2433 if (pCpu->pCurInstr->uOpcode == OP_OUTSB)2434 cb = 1;2435 else2436 cb = (pCpu->uOpMode == DISCPUMODE_16BIT) ? 2 : 4; /* dword in both 32 & 64 bits mode */2437 2438 VBOXSTRICTRC rcStrict = IOMInterpretCheckPortIOAccess(pVM, pRegFrame, Port, cb);2439 if (RT_UNLIKELY(rcStrict != VINF_SUCCESS))2440 {2441 AssertMsg(rcStrict == VINF_EM_RAW_GUEST_TRAP || rcStrict == VINF_TRPM_XCPT_DISPATCHED || RT_FAILURE(rcStrict), ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));2442 return rcStrict;2443 }2444 2445 return IOMInterpretOUTSEx(pVM, pVCpu, pRegFrame, Port, pCpu->fPrefix, (DISCPUMODE)pCpu->uAddrMode, cb);2446 }2447 #endif /* RC */2448 2505 2449 2506 #ifndef IN_RC -
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.