Changeset 74736 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Oct 10, 2018 12:05:41 PM (6 years ago)
- Location:
- trunk/src/VBox/VMM/VMMAll
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r74709 r74736 968 968 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX 969 969 IEM_STATIC VBOXSTRICTRC iemVmxVmexitTaskSwitch(PVMCPU pVCpu, IEMTASKSWITCH enmTaskSwitch, RTSEL SelNewTss); 970 IEM_STATIC VBOXSTRICTRC iemVmxVmexitEvent(PVMCPU pVCpu, uint8_t uVector, uint32_t fFlags, uint32_t uErrCode, uint64_t uCr2); 970 971 #endif 971 972 … … 5510 5511 #endif 5511 5512 5513 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX 5514 if (IEM_VMX_IS_NON_ROOT_MODE(pVCpu)) 5515 { 5516 VBOXSTRICTRC rcStrict0 = iemVmxVmexitEvent(pVCpu, u8Vector, fFlags, uErr, uCr2); 5517 if (rcStrict0 != VINF_VMX_INTERCEPT_NOT_ACTIVE) 5518 return rcStrict0; 5519 } 5520 #endif 5521 5512 5522 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM 5513 5523 if (CPUMIsGuestInSvmNestedHwVirtMode(IEM_GET_CTX(pVCpu))) … … 5517 5527 * intercepts in the nested-guest. However, secondary exceptions that occur 5518 5528 * during injection of any event -are- subject to exception intercepts. 5529 * 5519 5530 * See AMD spec. 15.20 "Event Injection". 5520 5531 */ 5521 5532 if (!pVCpu->cpum.GstCtx.hwvirt.svm.fInterceptEvents) 5522 pVCpu->cpum.GstCtx.hwvirt.svm.fInterceptEvents = 1;5533 pVCpu->cpum.GstCtx.hwvirt.svm.fInterceptEvents = true; 5523 5534 else 5524 5535 { -
trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
r74729 r74736 192 192 /* 1 */ RT_UOFFSETOF(VMXVVMCS, u32RoExitReason), 193 193 /* 2 */ RT_UOFFSETOF(VMXVVMCS, u32RoExitIntInfo), 194 /* 3 */ RT_UOFFSETOF(VMXVVMCS, u32RoExit ErrCode),194 /* 3 */ RT_UOFFSETOF(VMXVVMCS, u32RoExitIntErrCode), 195 195 /* 4 */ RT_UOFFSETOF(VMXVVMCS, u32RoIdtVectoringInfo), 196 196 /* 5 */ RT_UOFFSETOF(VMXVVMCS, u32RoIdtVectoringErrCode), … … 1336 1336 1337 1337 /** 1338 * Converts an IEM exception event type to a VMX event type. 1339 * 1340 * @returns The VMX event type. 1341 * @param uVector The interrupt / exception vector number. 1342 * @param fFlags The IEM event flag (see IEM_XCPT_FLAGS_XXX). 1343 */ 1344 DECLINLINE(uint8_t) iemVmxGetEventType(uint32_t uVector, uint32_t fFlags) 1345 { 1346 /* Paranoia (callers may use these interchangeably). */ 1347 AssertCompile(VMX_EXIT_INT_INFO_TYPE_NMI == VMX_IDT_VECTORING_INFO_TYPE_NMI); 1348 AssertCompile(VMX_EXIT_INT_INFO_TYPE_HW_XCPT == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT); 1349 AssertCompile(VMX_EXIT_INT_INFO_TYPE_EXT_INT == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT); 1350 AssertCompile(VMX_EXIT_INT_INFO_TYPE_SW_XCPT == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT); 1351 AssertCompile(VMX_EXIT_INT_INFO_TYPE_SW_INT == VMX_IDT_VECTORING_INFO_TYPE_SW_INT); 1352 AssertCompile(VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT); 1353 AssertCompile(VMX_EXIT_INT_INFO_TYPE_NMI == VMX_ENTRY_INT_INFO_TYPE_NMI); 1354 AssertCompile(VMX_EXIT_INT_INFO_TYPE_HW_XCPT == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT); 1355 AssertCompile(VMX_EXIT_INT_INFO_TYPE_EXT_INT == VMX_ENTRY_INT_INFO_TYPE_EXT_INT); 1356 AssertCompile(VMX_EXIT_INT_INFO_TYPE_SW_XCPT == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT); 1357 AssertCompile(VMX_EXIT_INT_INFO_TYPE_SW_INT == VMX_ENTRY_INT_INFO_TYPE_SW_INT); 1358 AssertCompile(VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT == VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT); 1359 1360 if (fFlags & IEM_XCPT_FLAGS_T_CPU_XCPT) 1361 { 1362 if (uVector == X86_XCPT_NMI) 1363 return VMX_EXIT_INT_INFO_TYPE_NMI; 1364 return VMX_EXIT_INT_INFO_TYPE_HW_XCPT; 1365 } 1366 1367 if (fFlags & IEM_XCPT_FLAGS_T_SOFT_INT) 1368 { 1369 if (fFlags & (IEM_XCPT_FLAGS_BP_INSTR | IEM_XCPT_FLAGS_OF_INSTR)) 1370 return VMX_EXIT_INT_INFO_TYPE_SW_XCPT; 1371 if (fFlags & IEM_XCPT_FLAGS_ICEBP_INSTR) 1372 return VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT; 1373 return VMX_EXIT_INT_INFO_TYPE_SW_INT; 1374 } 1375 1376 Assert(fFlags & IEM_XCPT_FLAGS_T_EXT_INT); 1377 return VMX_EXIT_INT_INFO_TYPE_EXT_INT; 1378 } 1379 1380 1381 /** 1338 1382 * Sets the VM-instruction error VMCS field. 1339 1383 * … … 1352 1396 * 1353 1397 * @param pVCpu The cross context virtual CPU structure. 1354 * @param uExitQual The VM-exit qualification field.1398 * @param uExitQual The VM-exit qualification. 1355 1399 */ 1356 1400 DECL_FORCE_INLINE(void) iemVmxVmcsSetExitQual(PVMCPU pVCpu, uint64_t uExitQual) … … 1362 1406 1363 1407 /** 1408 * Sets the VM-exit interruption information field. 1409 * 1410 * @param pVCpu The cross context virtual CPU structure. 1411 * @param uExitQual The VM-exit interruption information. 1412 */ 1413 DECL_FORCE_INLINE(void) iemVmxVmcsSetExitIntInfo(PVMCPU pVCpu, uint32_t uExitIntInfo) 1414 { 1415 PVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 1416 pVmcs->u32RoExitIntInfo = uExitIntInfo; 1417 } 1418 1419 1420 /** 1421 * Sets the VM-exit interruption error code. 1422 * 1423 * @param pVCpu The cross context virtual CPU structure. 1424 * @param uErrCode The error code. 1425 */ 1426 DECL_FORCE_INLINE(void) iemVmxVmcsSetExitIntErrCode(PVMCPU pVCpu, uint32_t uErrCode) 1427 { 1428 PVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 1429 pVmcs->u32RoExitIntErrCode = uErrCode; 1430 } 1431 1432 1433 /** 1434 * Sets the IDT-vectoring information field. 1435 * 1436 * @param pVCpu The cross context virtual CPU structure. 1437 * @param uIdtVectorInfo The IDT-vectoring information. 1438 */ 1439 DECL_FORCE_INLINE(void) iemVmxVmcsSetIdtVectoringInfo(PVMCPU pVCpu, uint32_t uIdtVectorInfo) 1440 { 1441 PVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 1442 pVmcs->u32RoIdtVectoringInfo = uIdtVectorInfo; 1443 } 1444 1445 1446 /** 1447 * Sets the IDT-vectoring error code field. 1448 * 1449 * @param pVCpu The cross context virtual CPU structure. 1450 * @param uErrCode The error code. 1451 */ 1452 DECL_FORCE_INLINE(void) iemVmxVmcsSetIdtVectoringErrCode(PVMCPU pVCpu, uint32_t uErrCode) 1453 { 1454 PVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 1455 pVmcs->u32RoIdtVectoringErrCode = uErrCode; 1456 } 1457 1458 1459 /** 1364 1460 * Sets the VM-exit guest-linear address VMCS field. 1365 1461 * 1366 1462 * @param pVCpu The cross context virtual CPU structure. 1367 * @param uGuestLinearAddr The VM-exit guest-linear address field.1463 * @param uGuestLinearAddr The VM-exit guest-linear address. 1368 1464 */ 1369 1465 DECL_FORCE_INLINE(void) iemVmxVmcsSetExitGuestLinearAddr(PVMCPU pVCpu, uint64_t uGuestLinearAddr) … … 1378 1474 * 1379 1475 * @param pVCpu The cross context virtual CPU structure. 1380 * @param uGuestPhysAddr The VM-exit guest-physical address field.1476 * @param uGuestPhysAddr The VM-exit guest-physical address. 1381 1477 */ 1382 1478 DECL_FORCE_INLINE(void) iemVmxVmcsSetExitGuestPhysAddr(PVMCPU pVCpu, uint64_t uGuestPhysAddr) … … 1407 1503 * 1408 1504 * @param pVCpu The cross context virtual CPU structure. 1409 * @param uExitInstrInfo The VM-exit instruction info . field.1505 * @param uExitInstrInfo The VM-exit instruction information. 1410 1506 */ 1411 1507 DECL_FORCE_INLINE(void) iemVmxVmcsSetExitInstrInfo(PVMCPU pVCpu, uint32_t uExitInstrInfo) … … 3474 3570 iemVmxVmcsSetExitQual(pVCpu, uExitQual); 3475 3571 return iemVmxVmexit(pVCpu, VMX_EXIT_TASK_SWITCH); 3572 } 3573 3574 3575 /** 3576 * VMX VM-exit handler for VM-exits due to delivery of an event (indirectly). 3577 * 3578 * @returns VBox strict status code. 3579 * @param pVCpu The cross context virtual CPU structure. 3580 * @param uVector The interrupt / exception vector number. 3581 * @param fFlags The flags (see IEM_XCPT_FLAGS_XXX). 3582 * @param uErrCode The error code associated with the event. 3583 * @param uCr2 The CR2 value in case of a \#PF exception. 3584 */ 3585 IEM_STATIC VBOXSTRICTRC iemVmxVmexitEvent(PVMCPU pVCpu, uint8_t uVector, uint32_t fFlags, uint32_t uErrCode, uint64_t uCr2) 3586 { 3587 PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 3588 Assert(pVmcs); 3589 3590 /* 3591 * If the event is being injected as part of VM-entry, it isn't subject to event 3592 * intercepts in the nested-guest. However, secondary exceptions that occur during 3593 * injection of any event -are- subject to event interception. 3594 * 3595 * See Intel spec. 26.5.1.2 "VM Exits During Event Injection". 3596 */ 3597 if (!pVCpu->cpum.GstCtx.hwvirt.vmx.fInterceptEvents) 3598 { 3599 /* Update the IDT-vectoring event in the VMCS as the source of the upcoming event. */ 3600 uint8_t const uIdtVectoringType = iemVmxGetEventType(uVector, fFlags); 3601 uint8_t const fErrCodeValid = (fFlags & IEM_XCPT_FLAGS_ERR); 3602 uint32_t const uIdtVectoringInfo = RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_VECTOR, uVector) 3603 | RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_TYPE, uIdtVectoringType) 3604 | RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_ERR_CODE_VALID, fErrCodeValid) 3605 | RT_BF_MAKE(VMX_BF_IDT_VECTORING_INFO_VALID, 1); 3606 iemVmxVmcsSetIdtVectoringInfo(pVCpu, uIdtVectoringInfo); 3607 iemVmxVmcsSetIdtVectoringErrCode(pVCpu, uErrCode); 3608 3609 pVCpu->cpum.GstCtx.hwvirt.vmx.fInterceptEvents = true; 3610 return VINF_VMX_INTERCEPT_NOT_ACTIVE; 3611 } 3612 3613 /* 3614 * Evaluate intercepts for hardware exceptions including #BP, #DB, #OF 3615 * generated by INT3, INT1 (ICEBP) and INTO respectively. 3616 */ 3617 bool fIntercept = false; 3618 bool fIsHwXcpt = false; 3619 if (fFlags & (IEM_XCPT_FLAGS_T_CPU_XCPT | IEM_XCPT_FLAGS_T_SOFT_INT)) 3620 { 3621 if ( !(fFlags & IEM_XCPT_FLAGS_T_SOFT_INT) 3622 || (fFlags & (IEM_XCPT_FLAGS_BP_INSTR | IEM_XCPT_FLAGS_OF_INSTR | IEM_XCPT_FLAGS_ICEBP_INSTR))) 3623 { 3624 fIsHwXcpt = true; 3625 do 3626 { 3627 /* NMIs have a dedicated VM-execution control for causing VM-exits. */ 3628 if (uVector == X86_XCPT_NMI) 3629 { 3630 fIntercept = RT_BOOL(pVmcs->u32PinCtls & VMX_PIN_CTLS_NMI_EXIT); 3631 break; 3632 } 3633 3634 /* Page-faults are subject to masking using its error code. */ 3635 uint32_t fXcptBitmap = pVmcs->u32XcptBitmap; 3636 if (uVector == X86_XCPT_PF) 3637 { 3638 uint32_t const fXcptPFMask = pVmcs->u32XcptPFMask; 3639 uint32_t const fXcptPFMatch = pVmcs->u32XcptPFMatch; 3640 if ((uErrCode & fXcptPFMask) != fXcptPFMatch) 3641 fXcptBitmap ^= RT_BIT(X86_XCPT_PF); 3642 } 3643 3644 /* Consult the exception bitmap. */ 3645 if (fXcptBitmap & RT_BIT(uVector)) 3646 fIntercept = true; 3647 } while (0); 3648 } 3649 /* else: Software interrupts cannot be intercepted and therefore do not cause a VM-exit. */ 3650 } 3651 else if (fFlags & IEM_XCPT_FLAGS_T_EXT_INT) 3652 { 3653 /* External interrupts have a dedicated VM-execution control for causing VM-exits. */ 3654 fIntercept = RT_BOOL(pVmcs->u32PinCtls & VMX_PIN_CTLS_EXT_INT_EXIT); 3655 3656 /** @todo NSTVMX: What about "acknowledge interrupt on exit" control? */ 3657 } 3658 3659 /* 3660 * Now that we've determined whether the external interrupt or hardware exception 3661 * causes a VM-exit, we need to construct the relevant VM-exit information and 3662 * cause the VM-exit. 3663 */ 3664 if (fIntercept) 3665 { 3666 uint64_t uExitQual = 0; 3667 if (fIsHwXcpt) 3668 { 3669 if (uVector == X86_XCPT_PF) 3670 uExitQual = uCr2; 3671 else if (uVector == X86_XCPT_DB) 3672 { 3673 IEM_CTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DR6); 3674 uExitQual = pVCpu->cpum.GstCtx.dr[6] & VMX_VMCS_EXIT_QUAL_VALID_MASK; 3675 } 3676 } 3677 3678 /* Construct the rest of the event related information fields and cause the VM-exit. */ 3679 uint32_t const uExitReason = (fFlags & IEM_XCPT_FLAGS_T_EXT_INT) ? VMX_EXIT_EXT_INT : VMX_EXIT_XCPT_OR_NMI; 3680 uint8_t const fNmiUnblocking = 0; /** @todo NSTVMX: Implement NMI-unblocking due to IRET. */ 3681 uint8_t const fErrCodeValid = (fFlags & IEM_XCPT_FLAGS_ERR); 3682 uint8_t const uIntInfoType = iemVmxGetEventType(uVector, fFlags); 3683 uint32_t const uExitIntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, uVector) 3684 | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_TYPE, uIntInfoType) 3685 | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_ERR_CODE_VALID, fErrCodeValid) 3686 | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_NMI_UNBLOCK_IRET, fNmiUnblocking) 3687 | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VALID, 1); 3688 iemVmxVmcsSetExitIntInfo(pVCpu, uExitIntInfo); 3689 iemVmxVmcsSetExitIntErrCode(pVCpu, uErrCode); 3690 iemVmxVmcsSetExitQual(pVCpu, uExitQual); 3691 iemVmxVmexit(pVCpu, uExitReason); 3692 } 3693 3694 return VINF_VMX_INTERCEPT_NOT_ACTIVE; 3476 3695 } 3477 3696
Note:
See TracChangeset
for help on using the changeset viewer.