Changeset 37034 in vbox
- Timestamp:
- May 10, 2011 6:10:46 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 71652
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/iem.h
r36794 r37034 28 28 29 29 #include <VBox/types.h> 30 #include <VBox/vmm/trpm.h> 30 31 31 32 … … 38 39 39 40 40 VMMDECL(VBOXSTRICTRC) IEMExecOne(PVMCPU pVCpu); 41 VMMDECL(VBOXSTRICTRC) IEMExecOne(PVMCPU pVCpu); 42 VMM_INT_DECL(VBOXSTRICTRC) IEMInjectTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType, uint16_t uErrCode, RTGCPTR uCr2); 41 43 42 44 #if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3) -
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r37013 r37034 1251 1251 1252 1252 static VBOXSTRICTRC iemRaiseSelectorInvalidAccess(PIEMCPU pIemCpu, uint32_t iSegReg, uint32_t fAccess) 1253 { 1254 AssertFailed(/** @todo implement this */); 1255 return VERR_NOT_IMPLEMENTED; 1256 } 1257 1258 1259 static VBOXSTRICTRC iemRaiseSelectorNotPresentWithErr(PIEMCPU pIemCpu, uint16_t uErr) 1253 1260 { 1254 1261 AssertFailed(/** @todo implement this */); … … 4535 4542 RTGCPTR uCr2; 4536 4543 int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrCode, &uCr2); AssertRC(rc2); 4537 Log(("Injecting trap %#x\n", u8TrapNo)); 4538 4539 uint32_t fFlags; 4540 switch (enmType) 4541 { 4542 case TRPM_HARDWARE_INT: 4543 fFlags = IEM_XCPT_FLAGS_T_EXT_INT; 4544 uErrCode = uCr2 = 0; 4545 break; 4546 case TRPM_SOFTWARE_INT: 4547 fFlags = IEM_XCPT_FLAGS_T_SOFT_INT; 4548 uErrCode = uCr2 = 0; 4549 break; 4550 case TRPM_TRAP: 4551 fFlags = IEM_XCPT_FLAGS_T_CPU_XCPT; 4552 if (u8TrapNo == X86_XCPT_PF) 4553 fFlags |= IEM_XCPT_FLAGS_CR2; 4554 switch (u8TrapNo) 4555 { 4556 case X86_XCPT_DF: 4557 case X86_XCPT_TS: 4558 case X86_XCPT_NP: 4559 case X86_XCPT_SS: 4560 case X86_XCPT_PF: 4561 case X86_XCPT_AC: 4562 fFlags |= IEM_XCPT_FLAGS_ERR; 4563 break; 4564 } 4565 TRPMHasTrap(pVCpu) 4566 break; 4567 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 4568 } 4569 iemCImpl_RaiseXcptOrInt(pIemCpu, 0, u8TrapNo, fFlags, (uint16_t)uErrCode, uCr2); 4544 IEMInjectTrap(pVCpu, u8TrapNo, enmType, (uint16_t)uErrCode, uCr2); 4570 4545 if (!IEM_VERIFICATION_ENABLED(pIemCpu)) 4571 4546 TRPMResetTrap(pVCpu); … … 5338 5313 } 5339 5314 5315 5316 /** 5317 * Injects a trap, fault, abort, software interrupt or external interrupt. 5318 * 5319 * The parameter list matches TRPMQueryTrapAll pretty closely. 5320 * 5321 * @returns Strict VBox status code. 5322 * @param pVCpu The current virtual CPU. 5323 * @param u8TrapNo The trap number. 5324 * @param enmType What type is it (trap/fault/abort), software 5325 * interrupt or hardware interrupt. 5326 * @param uErrCode The error code if applicable. 5327 * @param uCr2 The CR2 value if applicable. 5328 */ 5329 VMM_INT_DECL(VBOXSTRICTRC) IEMInjectTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType, uint16_t uErrCode, RTGCPTR uCr2) 5330 { 5331 uint32_t fFlags; 5332 switch (enmType) 5333 { 5334 case TRPM_HARDWARE_INT: 5335 Log(("IEMInjectTrap: %#4x ext\n", u8TrapNo)); 5336 fFlags = IEM_XCPT_FLAGS_T_EXT_INT; 5337 uErrCode = uCr2 = 0; 5338 break; 5339 5340 case TRPM_SOFTWARE_INT: 5341 Log(("IEMInjectTrap: %#4x soft\n", u8TrapNo)); 5342 fFlags = IEM_XCPT_FLAGS_T_SOFT_INT; 5343 uErrCode = uCr2 = 0; 5344 break; 5345 5346 case TRPM_TRAP: 5347 Log(("IEMInjectTrap: %#4x trap err=%#x cr2=%#RGv\n", u8TrapNo, uErrCode, uCr2)); 5348 fFlags = IEM_XCPT_FLAGS_T_CPU_XCPT; 5349 if (u8TrapNo == X86_XCPT_PF) 5350 fFlags |= IEM_XCPT_FLAGS_CR2; 5351 switch (u8TrapNo) 5352 { 5353 case X86_XCPT_DF: 5354 case X86_XCPT_TS: 5355 case X86_XCPT_NP: 5356 case X86_XCPT_SS: 5357 case X86_XCPT_PF: 5358 case X86_XCPT_AC: 5359 fFlags |= IEM_XCPT_FLAGS_ERR; 5360 break; 5361 } 5362 break; 5363 5364 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 5365 } 5366 5367 return iemCImpl_RaiseXcptOrInt(&pVCpu->iem.s, 0, u8TrapNo, fFlags, uErrCode, uCr2); 5368 } 5369 -
trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
r37013 r37034 1138 1138 1139 1139 1140 /** 1141 * Adjust the CPU state according to the exception being raised. 1142 * 1143 * @param pCtx The CPU context. 1144 * @param u8Vector The exception that has been raised. 1145 */ 1146 DECLINLINE(void) iemCImpl_RaiseXcptAdjustState(PCPUMCTX pCtx, uint8_t u8Vector) 1147 { 1148 switch (u8Vector) 1149 { 1150 case X86_XCPT_DB: 1151 pCtx->dr[7] &= ~X86_DR7_GD; 1152 break; 1153 /** @todo Read the AMD and Intel exception reference... */ 1154 } 1155 } 1156 1157 1158 /** 1159 * Implements exceptions and interrupts for real mode. 1160 * 1161 * @returns VBox strict status code. 1162 * @param pIemCpu The IEM per CPU instance data. 1163 * @param pCtx The CPU context. 1164 * @param cbInstr The number of bytes to offset rIP by in the return 1165 * address. 1166 * @param u8Vector The interrupt / exception vector number. 1167 * @param fFlags The flags. 1168 * @param uErr The error value if IEM_XCPT_FLAGS_ERR is set. 1169 * @param uCr2 The CR2 value if IEM_XCPT_FLAGS_CR2 is set. 1170 */ 1140 1171 static VBOXSTRICTRC 1141 iemCImpl_RaiseXcptOrIntAgain(PIEMCPU pIemCpu, 1142 uint8_t u8Vector, 1143 uint32_t fFlags, 1144 uint16_t uErr, 1145 uint64_t uCr2, 1146 uint8_t u8PrevVector); 1172 iemCImpl_RaiseXcptOrIntInRealMode(PIEMCPU pIemCpu, 1173 PCPUMCTX pCtx, 1174 uint8_t cbInstr, 1175 uint8_t u8Vector, 1176 uint32_t fFlags, 1177 uint16_t uErr, 1178 uint64_t uCr2) 1179 { 1180 AssertReturn(pIemCpu->enmCpuMode == IEMMODE_16BIT, VERR_INTERNAL_ERROR_3); 1181 1182 /* 1183 * Read the IDT entry. 1184 */ 1185 if (pCtx->idtr.cbIdt < UINT32_C(4) * u8Vector + 3) 1186 { 1187 Log(("RaiseXcptOrIntInRealMode: %#x is out of bounds (%#x)\n", u8Vector, pCtx->idtr.cbIdt)); 1188 return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT)); 1189 } 1190 RTFAR16 Idte; 1191 VBOXSTRICTRC rcStrict = iemMemFetchDataU32(pIemCpu, (uint32_t *)&Idte, UINT8_MAX, 1192 pCtx->idtr.pIdt + UINT32_C(4) * u8Vector); 1193 if (RT_UNLIKELY(rcStrict != VINF_SUCCESS)) 1194 return rcStrict; 1195 1196 /* 1197 * Push the stack frame. 1198 */ 1199 uint16_t *pu16Frame; 1200 uint64_t uNewRsp; 1201 rcStrict = iemMemStackPushBeginSpecial(pIemCpu, 6, (void **)&pu16Frame, &uNewRsp); 1202 if (rcStrict != VINF_SUCCESS) 1203 return rcStrict; 1204 1205 pu16Frame[2] = (uint16_t)pCtx->eflags.u; 1206 pu16Frame[1] = (uint16_t)pCtx->cs; 1207 pu16Frame[0] = pCtx->ip + cbInstr; 1208 rcStrict = iemMemStackPushCommitSpecial(pIemCpu, pu16Frame, uNewRsp); 1209 if (RT_UNLIKELY(rcStrict != VINF_SUCCESS)) 1210 return rcStrict; 1211 1212 /* 1213 * Load the vector address into cs:ip and make exception specific state 1214 * adjustments. 1215 */ 1216 pCtx->cs = Idte.sel; 1217 pCtx->csHid.u64Base = (uint32_t)Idte.sel << 4; 1218 /** @todo do we load attribs and limit as well? Should we check against limit like far jump? */ 1219 pCtx->rip = Idte.off; 1220 pCtx->eflags.Bits.u1IF = 0; 1221 1222 /** @todo do we actually do this in real mode? */ 1223 if (fFlags & IEM_XCPT_FLAGS_T_CPU_XCPT) 1224 iemCImpl_RaiseXcptAdjustState(pCtx, u8Vector); 1225 1226 return VINF_SUCCESS; 1227 } 1228 1229 1230 /** 1231 * Implements exceptions and interrupts for protected mode. 1232 * 1233 * @returns VBox strict status code. 1234 * @param pIemCpu The IEM per CPU instance data. 1235 * @param pCtx The CPU context. 1236 * @param cbInstr The number of bytes to offset rIP by in the return 1237 * address. 1238 * @param u8Vector The interrupt / exception vector number. 1239 * @param fFlags The flags. 1240 * @param uErr The error value if IEM_XCPT_FLAGS_ERR is set. 1241 * @param uCr2 The CR2 value if IEM_XCPT_FLAGS_CR2 is set. 1242 */ 1243 static VBOXSTRICTRC 1244 iemCImpl_RaiseXcptOrIntInProtMode(PIEMCPU pIemCpu, 1245 PCPUMCTX pCtx, 1246 uint8_t cbInstr, 1247 uint8_t u8Vector, 1248 uint32_t fFlags, 1249 uint16_t uErr, 1250 uint64_t uCr2) 1251 { 1252 /* 1253 * Read the IDT entry. 1254 */ 1255 if (pCtx->idtr.cbIdt < UINT32_C(8) * u8Vector + 7) 1256 { 1257 Log(("RaiseXcptOrIntInProtMode: %#x is out of bounds (%#x)\n", u8Vector, pCtx->idtr.cbIdt)); 1258 return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT)); 1259 } 1260 X86DESC Idte; 1261 VBOXSTRICTRC rcStrict = iemMemFetchDataU64(pIemCpu, &Idte.u, UINT8_MAX, 1262 pCtx->idtr.pIdt + UINT32_C(8) * u8Vector); 1263 if (RT_UNLIKELY(rcStrict != VINF_SUCCESS)) 1264 return rcStrict; 1265 1266 /* 1267 * Check the descriptor type, DPL and such. 1268 * ASSUMES this is done in the same order as described for selectors. 1269 */ 1270 if (Idte.Gate.u1DescType) 1271 { 1272 Log(("RaiseXcptOrIntInProtMode %#x - not system selector (%#x) -> #GP\n", u8Vector, Idte.Gate.u4Type)); 1273 return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT)); 1274 } 1275 uint32_t fEflToClear = X86_EFL_TF | X86_EFL_NT | X86_EFL_RF | X86_EFL_VM; 1276 switch (Idte.Gate.u4Type) 1277 { 1278 case X86_SEL_TYPE_SYS_UNDEFINED: 1279 case X86_SEL_TYPE_SYS_286_TSS_AVAIL: 1280 case X86_SEL_TYPE_SYS_LDT: 1281 case X86_SEL_TYPE_SYS_286_TSS_BUSY: 1282 case X86_SEL_TYPE_SYS_286_CALL_GATE: 1283 case X86_SEL_TYPE_SYS_UNDEFINED2: 1284 case X86_SEL_TYPE_SYS_386_TSS_AVAIL: 1285 case X86_SEL_TYPE_SYS_UNDEFINED3: 1286 case X86_SEL_TYPE_SYS_386_TSS_BUSY: 1287 case X86_SEL_TYPE_SYS_386_CALL_GATE: 1288 case X86_SEL_TYPE_SYS_UNDEFINED4: 1289 { 1290 /** @todo check what actually happens when the type is wrong... 1291 * esp. call gates. */ 1292 Log(("RaiseXcptOrIntInProtMode %#x - invalid type (%#x) -> #GP\n", u8Vector, Idte.Gate.u4Type)); 1293 return iemRaiseGeneralProtectionFault(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT)); 1294 } 1295 1296 case X86_SEL_TYPE_SYS_286_INT_GATE: 1297 case X86_SEL_TYPE_SYS_386_INT_GATE: 1298 fEflToClear |= X86_EFL_IF; 1299 break; 1300 1301 case X86_SEL_TYPE_SYS_TASK_GATE: 1302 case X86_SEL_TYPE_SYS_286_TRAP_GATE: 1303 case X86_SEL_TYPE_SYS_386_TRAP_GATE: 1304 break; 1305 1306 IEM_NOT_REACHED_DEFAULT_CASE_RET(); 1307 } 1308 1309 /* Check DPL against CPL if applicable. */ 1310 if (fFlags & IEM_XCPT_FLAGS_T_SOFT_INT) 1311 { 1312 #if 0 /** @todo continue here */ 1313 if (pIemCpu->uCpl > Desc.Legacy.Gen.u2Dpl) 1314 { 1315 Log(("load sreg%u, %#x - CPL (%d) is greater than DPL (%d) -> #GP\n", 1316 iSegReg, uSel, pIemCpu->uCpl, Desc.Legacy.Gen.u2Dpl)); 1317 return iemRaiseGeneralProtectionFault(pIemCpu, uSel & (X86_SEL_MASK | X86_SEL_LDT)); 1318 } 1319 #endif 1320 } 1321 1322 /* Is it there? */ 1323 if (!Idte.Gate.u1Present) 1324 { 1325 Log(("RaiseXcptOrIntInProtMode %#x - not present -> #NP\n", u8Vector)); 1326 return iemRaiseSelectorNotPresentWithErr(pIemCpu, X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT)); 1327 } 1328 1329 return VERR_NOT_IMPLEMENTED; 1330 } 1331 1332 1333 /** 1334 * Implements exceptions and interrupts for long mode. 1335 * 1336 * @returns VBox strict status code. 1337 * @param pIemCpu The IEM per CPU instance data. 1338 * @param pCtx The CPU context. 1339 * @param cbInstr The number of bytes to offset rIP by in the return 1340 * address. 1341 * @param u8Vector The interrupt / exception vector number. 1342 * @param fFlags The flags. 1343 * @param uErr The error value if IEM_XCPT_FLAGS_ERR is set. 1344 * @param uCr2 The CR2 value if IEM_XCPT_FLAGS_CR2 is set. 1345 */ 1346 static VBOXSTRICTRC 1347 iemCImpl_RaiseXcptOrIntInLongMode(PIEMCPU pIemCpu, 1348 PCPUMCTX pCtx, 1349 uint8_t cbInstr, 1350 uint8_t u8Vector, 1351 uint32_t fFlags, 1352 uint16_t uErr, 1353 uint64_t uCr2) 1354 { 1355 AssertMsgFailed(("long mode exception / interrupt dispatching\n")); 1356 return VERR_NOT_IMPLEMENTED; 1357 } 1358 1147 1359 1148 1360 /** 1149 1361 * Implements exceptions and interrupts. 1362 * 1363 * All exceptions and interrupts goes thru this function! 1150 1364 * 1151 1365 * @returns VBox strict status code. … … 1166 1380 uint64_t uCr2) 1167 1381 { 1168 /** @todo we should call TRPM to do this job. */ 1382 /* 1383 * Do recursion accounting. 1384 */ 1385 uint8_t uPrevXcpt = pIemCpu->uCurXcpt; 1386 if (pIemCpu->cXcptRecursions > 0) 1387 { 1388 /** @todo double and tripple faults. */ 1389 AssertReturn(pIemCpu->cXcptRecursions < 3, VERR_NOT_IMPLEMENTED); 1390 } 1391 pIemCpu->cXcptRecursions++; 1392 pIemCpu->uCurXcpt = u8Vector; 1393 1394 /* 1395 * Call mode specific worker function. 1396 */ 1169 1397 VBOXSTRICTRC rcStrict; 1170 1398 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 1171 1172 /* 1173 * Real mode is easy. 1174 */ 1175 if ( pIemCpu->enmCpuMode == IEMMODE_16BIT 1176 && IEM_IS_REAL_MODE(pIemCpu)) 1177 { 1178 /* read the IDT entry. */ 1179 if (pCtx->idtr.cbIdt < UINT32_C(4) * u8Vector + 3) 1180 return iemCImpl_RaiseXcptOrIntAgain(pIemCpu, 1181 X86_XCPT_GP, 1182 IEM_XCPT_FLAGS_T_CPU_XCPT | IEM_XCPT_FLAGS_ERR 1183 | (fFlags & IEM_XCPT_FLAGS_NESTING_MASK), 1184 X86_TRAP_ERR_IDT | ((uint16_t)u8Vector << X86_TRAP_ERR_SEL_SHIFT), 1185 0, 1186 u8Vector); 1187 RTFAR16 Idte; 1188 rcStrict = iemMemFetchDataU32(pIemCpu, (uint32_t *)&Idte, UINT8_MAX, pCtx->idtr.pIdt + UINT32_C(4) * u8Vector); 1189 if (RT_UNLIKELY(rcStrict != VINF_SUCCESS)) 1190 return rcStrict; 1191 1192 /* push the stack frame. */ 1193 uint16_t *pu16Frame; 1194 uint64_t uNewRsp; 1195 rcStrict = iemMemStackPushBeginSpecial(pIemCpu, 6, (void **)&pu16Frame, &uNewRsp); 1196 if (rcStrict != VINF_SUCCESS) 1197 return rcStrict; 1198 1199 pu16Frame[2] = (uint16_t)pCtx->eflags.u; 1200 pu16Frame[1] = (uint16_t)pCtx->cs; 1201 pu16Frame[0] = pCtx->ip + cbInstr; 1202 rcStrict = iemMemStackPushCommitSpecial(pIemCpu, pu16Frame, uNewRsp); 1203 if (RT_UNLIKELY(rcStrict != VINF_SUCCESS)) 1204 return rcStrict; 1205 1206 /* load the vector address into cs:ip. */ 1207 pCtx->cs = Idte.sel; 1208 pCtx->csHid.u64Base = (uint32_t)Idte.sel << 4; 1209 /** @todo do we load attribs and limit as well? Should we check against limit like far jump? */ 1210 pCtx->rip = Idte.off; 1211 pCtx->eflags.Bits.u1IF = 0; 1212 return VINF_SUCCESS; 1213 } 1214 1215 /* 1216 * continue here... 1217 */ 1218 AssertFailed(); 1219 return VERR_NOT_IMPLEMENTED; 1220 } 1221 1222 1223 /** 1224 * Deals with exceptions occuring while dispatching an exception or interrupt. 1225 * 1226 * @returns VBox strict status code. 1227 * @param pIemCpu The IEM per CPU instance data. 1228 * @param u8Vector The exception vector number. 1229 * @param fFlags The flags. 1230 * @param uErr The error value if IEM_XCPT_FLAGS_ERR is set. 1231 * @param uCr2 The CR2 value if IEM_XCPT_FLAGS_CR2 is set. 1232 * @param u8PrevVector The exception we tried raising. 1233 */ 1234 static VBOXSTRICTRC 1235 iemCImpl_RaiseXcptOrIntAgain(PIEMCPU pIemCpu, 1236 uint8_t u8Vector, 1237 uint32_t fFlags, 1238 uint16_t uErr, 1239 uint64_t uCr2, 1240 uint8_t u8PrevVector) 1241 { 1242 return iemCImpl_RaiseXcptOrInt(pIemCpu, 0, u8Vector, fFlags, uErr, uCr2); 1243 } 1244 1399 if (!(pCtx->cr0 & X86_CR0_PE)) 1400 rcStrict = iemCImpl_RaiseXcptOrIntInRealMode(pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2); 1401 else if (pCtx->msrEFER & MSR_K6_EFER_LMA) 1402 rcStrict = iemCImpl_RaiseXcptOrIntInLongMode(pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2); 1403 else 1404 rcStrict = iemCImpl_RaiseXcptOrIntInProtMode(pIemCpu, pCtx, cbInstr, u8Vector, fFlags, uErr, uCr2); 1405 1406 /* 1407 * Unwind. 1408 */ 1409 pIemCpu->cXcptRecursions--; 1410 pIemCpu->uCurXcpt = uPrevXcpt; 1411 return rcStrict; 1412 } 1245 1413 1246 1414 … … 1253 1421 IEM_CIMPL_DEF_2(iemCImpl_int, uint8_t, u8Int, bool, fIsBpInstr) 1254 1422 { 1423 Assert(pIemCpu->cXcptRecursions == 0); 1255 1424 return iemCImpl_RaiseXcptOrInt(pIemCpu, 1256 1425 cbInstr, -
trunk/src/VBox/VMM/include/IEMInternal.h
r37002 r37034 147 147 bool fByPassHandlers; 148 148 /** Explicit alignment padding. */ 149 bool afAlignment0[6]; 150 149 bool afAlignment0[4]; 150 151 /** Exception / interrupt recursion depth. */ 152 int8_t cXcptRecursions; 153 /** The current exception / interrupt . */ 154 uint8_t uCurXcpt; 151 155 /** The CPL. */ 152 156 uint8_t uCpl;
Note:
See TracChangeset
for help on using the changeset viewer.