- Timestamp:
- Aug 6, 2017 3:21:45 AM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 117424
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
r68301 r68305 97 97 pVCpu->hm.s.idEnteredCpu, RTMpCpuId())); 98 98 99 /** Exception bitmap mask for all contributory exceptions. 99 /** 100 * Exception bitmap mask for all contributory exceptions. 100 101 * 101 102 * Page fault is deliberately excluded here as it's conditional as to whether … … 104 105 #define HMSVM_CONTRIBUTORY_XCPT_MASK ( RT_BIT(X86_XCPT_GP) | RT_BIT(X86_XCPT_NP) | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_TS) \ 105 106 | RT_BIT(X86_XCPT_DE)) 107 108 /** 109 * Mandatory/unconditional guest control intercepts. 110 */ 111 #define HMSVM_MANDATORY_GUEST_CTRL_INTERCEPTS ( SVM_CTRL_INTERCEPT_INTR \ 112 | SVM_CTRL_INTERCEPT_NMI \ 113 | SVM_CTRL_INTERCEPT_INIT \ 114 | SVM_CTRL_INTERCEPT_RDPMC \ 115 | SVM_CTRL_INTERCEPT_CPUID \ 116 | SVM_CTRL_INTERCEPT_RSM \ 117 | SVM_CTRL_INTERCEPT_HLT \ 118 | SVM_CTRL_INTERCEPT_IOIO_PROT \ 119 | SVM_CTRL_INTERCEPT_MSR_PROT \ 120 | SVM_CTRL_INTERCEPT_INVLPGA \ 121 | SVM_CTRL_INTERCEPT_SHUTDOWN \ 122 | SVM_CTRL_INTERCEPT_FERR_FREEZE \ 123 | SVM_CTRL_INTERCEPT_VMRUN \ 124 | SVM_CTRL_INTERCEPT_VMMCALL \ 125 | SVM_CTRL_INTERCEPT_VMLOAD \ 126 | SVM_CTRL_INTERCEPT_VMSAVE \ 127 | SVM_CTRL_INTERCEPT_STGI \ 128 | SVM_CTRL_INTERCEPT_CLGI \ 129 | SVM_CTRL_INTERCEPT_SKINIT \ 130 | SVM_CTRL_INTERCEPT_WBINVD \ 131 | SVM_CTRL_INTERCEPT_MONITOR \ 132 | SVM_CTRL_INTERCEPT_MWAIT \ 133 | SVM_CTRL_INTERCEPT_XSETBV) 134 135 /** 136 * Mandatory/unconditional nested-guest control intercepts. 137 */ 138 #define HMSVM_MANDATORY_NESTED_GUEST_CTRL_INTERCEPTS ( HMSVM_MANDATORY_GUEST_CTRL_INTERCEPTS \ 139 | SVM_CTRL_INTERCEPT_SMI) 106 140 107 141 /** @name VMCB Clean Bits. … … 251 285 static FNSVMEXITHANDLER hmR0SvmExitMwait; 252 286 static FNSVMEXITHANDLER hmR0SvmExitShutdown; 287 static FNSVMEXITHANDLER hmR0SvmExitUnexpected; 253 288 static FNSVMEXITHANDLER hmR0SvmExitReadCRx; 254 289 static FNSVMEXITHANDLER hmR0SvmExitWriteCRx; … … 705 740 706 741 /* Set up unconditional intercepts and conditions. */ 707 pVmcb->ctrl.u64InterceptCtrl = SVM_CTRL_INTERCEPT_INTR /* External interrupt causes a #VMEXIT. */ 708 | SVM_CTRL_INTERCEPT_NMI /* Non-maskable interrupts causes a #VMEXIT. */ 709 | SVM_CTRL_INTERCEPT_INIT /* INIT signal causes a #VMEXIT. */ 710 | SVM_CTRL_INTERCEPT_RDPMC /* RDPMC causes a #VMEXIT. */ 711 | SVM_CTRL_INTERCEPT_CPUID /* CPUID causes a #VMEXIT. */ 712 | SVM_CTRL_INTERCEPT_RSM /* RSM causes a #VMEXIT. */ 713 | SVM_CTRL_INTERCEPT_HLT /* HLT causes a #VMEXIT. */ 714 | SVM_CTRL_INTERCEPT_IOIO_PROT /* Use the IOPM to cause IOIO #VMEXITs. */ 715 | SVM_CTRL_INTERCEPT_MSR_PROT /* MSR access not covered by MSRPM causes a #VMEXIT.*/ 716 | SVM_CTRL_INTERCEPT_INVLPGA /* INVLPGA causes a #VMEXIT. */ 717 | SVM_CTRL_INTERCEPT_SHUTDOWN /* Shutdown events causes a #VMEXIT. */ 718 | SVM_CTRL_INTERCEPT_FERR_FREEZE /* Intercept "freezing" during legacy FPU handling. */ 719 | SVM_CTRL_INTERCEPT_VMRUN /* VMRUN causes a #VMEXIT. */ 720 | SVM_CTRL_INTERCEPT_VMMCALL /* VMMCALL causes a #VMEXIT. */ 721 | SVM_CTRL_INTERCEPT_VMLOAD /* VMLOAD causes a #VMEXIT. */ 722 | SVM_CTRL_INTERCEPT_VMSAVE /* VMSAVE causes a #VMEXIT. */ 723 | SVM_CTRL_INTERCEPT_STGI /* STGI causes a #VMEXIT. */ 724 | SVM_CTRL_INTERCEPT_CLGI /* CLGI causes a #VMEXIT. */ 725 | SVM_CTRL_INTERCEPT_SKINIT /* SKINIT causes a #VMEXIT. */ 726 | SVM_CTRL_INTERCEPT_WBINVD /* WBINVD causes a #VMEXIT. */ 727 | SVM_CTRL_INTERCEPT_MONITOR /* MONITOR causes a #VMEXIT. */ 728 | SVM_CTRL_INTERCEPT_MWAIT /* MWAIT causes a #VMEXIT. */ 729 | SVM_CTRL_INTERCEPT_XSETBV; /* XSETBV causes a #VMEXIT. */ 742 pVmcb->ctrl.u64InterceptCtrl = HMSVM_MANDATORY_GUEST_CTRL_INTERCEPTS; 730 743 731 744 /* CR0, CR4 reads must be intercepted, our shadow values are not necessarily the same as the guest's. */ … … 1744 1757 * well and handle it accordingly. 1745 1758 * 1746 * @param pVCpu The cross context virtual CPU structure.1747 1759 * @param pVmcb Pointer to the VM control block. 1748 1760 * @param pVmcbNstGst Pointer to the nested-guest VM control block. 1749 1761 */ 1750 static void hmR0SvmMergeIntercepts(PVMCPU pVCpu, PCSVMVMCB pVmcb, PSVMVMCB pVmcbNstGst) 1751 { 1752 RT_NOREF(pVCpu); 1753 #if 0 1762 static void hmR0SvmMergeIntercepts(PCSVMVMCB pVmcb, PSVMVMCB pVmcbNstGst) 1763 { 1754 1764 pVmcbNstGst->ctrl.u16InterceptRdCRx |= pVmcb->ctrl.u16InterceptRdCRx; 1755 1765 pVmcbNstGst->ctrl.u16InterceptWrCRx |= pVmcb->ctrl.u16InterceptWrCRx; 1756 pVmcbNstGst->ctrl.u16InterceptRdDRx |= pVmcb->ctrl.u16InterceptRdDRx; 1757 pVmcbNstGst->ctrl.u16InterceptWrDRx |= pVmcb->ctrl.u16InterceptWrDRx; 1758 #endif 1766 1767 /** @todo Figure out debugging with nested-guests, till then just intercept 1768 * all DR[0-15] accesses. */ 1769 pVmcbNstGst->ctrl.u16InterceptRdDRx |= 0xffff; 1770 pVmcbNstGst->ctrl.u16InterceptWrDRx |= 0xffff; 1771 1759 1772 pVmcbNstGst->ctrl.u32InterceptXcpt |= pVmcb->ctrl.u32InterceptXcpt; 1760 pVmcbNstGst->ctrl.u64InterceptCtrl |= pVmcb->ctrl.u64InterceptCtrl; 1773 pVmcbNstGst->ctrl.u64InterceptCtrl |= pVmcb->ctrl.u64InterceptCtrl 1774 | HMSVM_MANDATORY_NESTED_GUEST_CTRL_INTERCEPTS; 1775 1776 Assert((pVmcbNstGst->ctrl.u64InterceptCtrl & HMSVM_MANDATORY_GUEST_CTRL_INTERCEPTS) == HMSVM_MANDATORY_GUEST_CTRL_INTERCEPTS); 1761 1777 } 1762 1778 #endif … … 2035 2051 */ 2036 2052 PCSVMVMCB pVmcb = pVCpu->hm.s.svm.pVmcb; 2037 hmR0SvmMergeIntercepts(pV Cpu, pVmcb, pVmcbNstGst);2053 hmR0SvmMergeIntercepts(pVmcb, pVmcbNstGst); 2038 2054 2039 2055 HMCPU_CF_CLEAR(pVCpu, HM_CHANGED_SVM_NESTED_GUEST); … … 2615 2631 Log4(("hmR0SvmSetPendingEvent: u=%#RX64 u8Vector=%#x Type=%#x ErrorCodeValid=%RTbool ErrorCode=%#RX32\n", pEvent->u, 2616 2632 pEvent->n.u8Vector, (uint8_t)pEvent->n.u3Type, !!pEvent->n.u1ErrorCodeValid, pEvent->n.u32ErrorCode)); 2633 } 2634 2635 2636 /** 2637 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM. 2638 * 2639 * @param pVCpu The cross context virtual CPU structure. 2640 */ 2641 DECLINLINE(void) hmR0SvmSetPendingXcptUD(PVMCPU pVCpu) 2642 { 2643 SVMEVENT Event; 2644 Event.u = 0; 2645 Event.n.u1Valid = 1; 2646 Event.n.u3Type = SVM_EVENT_EXCEPTION; 2647 Event.n.u8Vector = X86_XCPT_UD; 2648 hmR0SvmSetPendingEvent(pVCpu, &Event, 0 /* GCPtrFaultAddress */); 2649 } 2650 2651 2652 /** 2653 * Sets a debug (\#DB) exception as pending-for-injection into the VM. 2654 * 2655 * @param pVCpu The cross context virtual CPU structure. 2656 */ 2657 DECLINLINE(void) hmR0SvmSetPendingXcptDB(PVMCPU pVCpu) 2658 { 2659 SVMEVENT Event; 2660 Event.u = 0; 2661 Event.n.u1Valid = 1; 2662 Event.n.u3Type = SVM_EVENT_EXCEPTION; 2663 Event.n.u8Vector = X86_XCPT_DB; 2664 hmR0SvmSetPendingEvent(pVCpu, &Event, 0 /* GCPtrFaultAddress */); 2665 } 2666 2667 2668 /** 2669 * Sets a page fault (\#PF) exception as pending-for-injection into the VM. 2670 * 2671 * @param pVCpu The cross context virtual CPU structure. 2672 * @param pCtx Pointer to the guest-CPU context. 2673 * @param u32ErrCode The error-code for the page-fault. 2674 * @param uFaultAddress The page fault address (CR2). 2675 * 2676 * @remarks This updates the guest CR2 with @a uFaultAddress! 2677 */ 2678 DECLINLINE(void) hmR0SvmSetPendingXcptPF(PVMCPU pVCpu, PCPUMCTX pCtx, uint32_t u32ErrCode, RTGCUINTPTR uFaultAddress) 2679 { 2680 SVMEVENT Event; 2681 Event.u = 0; 2682 Event.n.u1Valid = 1; 2683 Event.n.u3Type = SVM_EVENT_EXCEPTION; 2684 Event.n.u8Vector = X86_XCPT_PF; 2685 Event.n.u1ErrorCodeValid = 1; 2686 Event.n.u32ErrorCode = u32ErrCode; 2687 2688 /* Update CR2 of the guest. */ 2689 if (pCtx->cr2 != uFaultAddress) 2690 { 2691 pCtx->cr2 = uFaultAddress; 2692 HMCPU_CF_SET(pVCpu, HM_CHANGED_GUEST_CR2); 2693 } 2694 2695 hmR0SvmSetPendingEvent(pVCpu, &Event, uFaultAddress); 2696 } 2697 2698 2699 /** 2700 * Sets a device-not-available (\#NM) exception as pending-for-injection into 2701 * the VM. 2702 * 2703 * @param pVCpu The cross context virtual CPU structure. 2704 */ 2705 DECLINLINE(void) hmR0SvmSetPendingXcptNM(PVMCPU pVCpu) 2706 { 2707 SVMEVENT Event; 2708 Event.u = 0; 2709 Event.n.u1Valid = 1; 2710 Event.n.u3Type = SVM_EVENT_EXCEPTION; 2711 Event.n.u8Vector = X86_XCPT_NM; 2712 hmR0SvmSetPendingEvent(pVCpu, &Event, 0 /* GCPtrFaultAddress */); 2713 } 2714 2715 2716 /** 2717 * Sets a math-fault (\#MF) exception as pending-for-injection into the VM. 2718 * 2719 * @param pVCpu The cross context virtual CPU structure. 2720 */ 2721 DECLINLINE(void) hmR0SvmSetPendingXcptMF(PVMCPU pVCpu) 2722 { 2723 SVMEVENT Event; 2724 Event.u = 0; 2725 Event.n.u1Valid = 1; 2726 Event.n.u3Type = SVM_EVENT_EXCEPTION; 2727 Event.n.u8Vector = X86_XCPT_MF; 2728 hmR0SvmSetPendingEvent(pVCpu, &Event, 0 /* GCPtrFaultAddress */); 2729 } 2730 2731 2732 /** 2733 * Sets a double fault (\#DF) exception as pending-for-injection into the VM. 2734 * 2735 * @param pVCpu The cross context virtual CPU structure. 2736 */ 2737 DECLINLINE(void) hmR0SvmSetPendingXcptDF(PVMCPU pVCpu) 2738 { 2739 SVMEVENT Event; 2740 Event.u = 0; 2741 Event.n.u1Valid = 1; 2742 Event.n.u3Type = SVM_EVENT_EXCEPTION; 2743 Event.n.u8Vector = X86_XCPT_DF; 2744 Event.n.u1ErrorCodeValid = 1; 2745 Event.n.u32ErrorCode = 0; 2746 hmR0SvmSetPendingEvent(pVCpu, &Event, 0 /* GCPtrFaultAddress */); 2617 2747 } 2618 2748 … … 4344 4474 switch (pSvmTransient->u64ExitCode) 4345 4475 { 4346 #if 04347 case SVM_EXIT_NPF:4348 {4349 /** @todo. */4350 break;4351 }4352 #endif4353 4354 4476 case SVM_EXIT_CPUID: 4355 4477 { … … 4448 4570 { 4449 4571 Assert(!pVmcbNstGstCtrl->NestedPaging.n.u1NestedPaging); 4450 return hmR0SvmExecVmexit(pVCpu, pCtx); 4572 if (pVmcbNstGstCache->u32InterceptXcpt & RT_BIT(X86_XCPT_PF)) 4573 return hmR0SvmExecVmexit(pVCpu, pCtx); 4574 4575 /* If the nested-guest isn't for intercepting #PFs, simply forward the #PF to the guest. */ 4576 uint32_t const u32ErrCode = pVmcbNstGstCtrl->u64ExitInfo1; 4577 RTGCUINTPTR const uFaultAddress = pVmcbNstGstCtrl->u64ExitInfo2; 4578 hmR0SvmSetPendingXcptPF(pVCpu, pCtx, u32ErrCode, uFaultAddress); 4579 return VINF_SUCCESS; 4451 4580 } 4452 4581 … … 4474 4603 { 4475 4604 if (pVmcbNstGstCache->u16InterceptRdCRx & (1U << (uint16_t)(pSvmTransient->u64ExitCode - SVM_EXIT_READ_CR0))) 4476 hmR0SvmExecVmexit(pVCpu, pCtx);4605 return hmR0SvmExecVmexit(pVCpu, pCtx); 4477 4606 return hmR0SvmExitReadCRx(pVCpu, pCtx, pSvmTransient); 4478 4607 } … … 4484 4613 { 4485 4614 if (pVmcbNstGstCache->u16InterceptWrCRx & (1U << (uint16_t)(pSvmTransient->u64ExitCode - SVM_EXIT_WRITE_CR0))) 4486 hmR0SvmExecVmexit(pVCpu, pCtx);4615 return hmR0SvmExecVmexit(pVCpu, pCtx); 4487 4616 return hmR0SvmExitWriteCRx(pVCpu, pCtx, pSvmTransient); 4488 4617 } 4618 4619 case SVM_EXIT_PAUSE: 4620 { 4621 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_PAUSE) 4622 return hmR0SvmExecVmexit(pVCpu, pCtx); 4623 return hmR0SvmExitPause(pVCpu, pCtx, pSvmTransient); 4624 } 4625 4626 case SVM_EXIT_VINTR: 4627 { 4628 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_VINTR) 4629 return hmR0SvmExecVmexit(pVCpu, pCtx); 4630 return hmR0SvmExitVIntr(pVCpu, pCtx, pSvmTransient); 4631 } 4632 4633 case SVM_EXIT_INTR: 4634 { 4635 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_INTR) 4636 return hmR0SvmExecVmexit(pVCpu, pCtx); 4637 return hmR0SvmExitIntr(pVCpu, pCtx, pSvmTransient); 4638 } 4639 4640 case SVM_EXIT_FERR_FREEZE: 4641 { 4642 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_FERR_FREEZE) 4643 return hmR0SvmExecVmexit(pVCpu, pCtx); 4644 return hmR0SvmExitIntr(pVCpu, pCtx, pSvmTransient); 4645 } 4646 4647 case SVM_EXIT_NMI: 4648 { 4649 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_NMI) 4650 return hmR0SvmExecVmexit(pVCpu, pCtx); 4651 return hmR0SvmExitIntr(pVCpu, pCtx, pSvmTransient); 4652 } 4653 4654 case SVM_EXIT_INVLPG: 4655 { 4656 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_INVLPG) 4657 return hmR0SvmExecVmexit(pVCpu, pCtx); 4658 return hmR0SvmExitInvlpg(pVCpu, pCtx, pSvmTransient); 4659 } 4660 4661 case SVM_EXIT_WBINVD: 4662 { 4663 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_WBINVD) 4664 return hmR0SvmExecVmexit(pVCpu, pCtx); 4665 return hmR0SvmExitWbinvd(pVCpu, pCtx, pSvmTransient); 4666 } 4667 4668 case SVM_EXIT_INVD: 4669 { 4670 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_INVD) 4671 return hmR0SvmExecVmexit(pVCpu, pCtx); 4672 return hmR0SvmExitInvd(pVCpu, pCtx, pSvmTransient); 4673 } 4674 4675 case SVM_EXIT_RDPMC: 4676 { 4677 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_RDPMC) 4678 return hmR0SvmExecVmexit(pVCpu, pCtx); 4679 return hmR0SvmExitRdpmc(pVCpu, pCtx, pSvmTransient); 4680 } 4681 4682 default: 4683 { 4684 switch (pSvmTransient->u64ExitCode) 4685 { 4686 case SVM_EXIT_READ_DR0: case SVM_EXIT_READ_DR1: case SVM_EXIT_READ_DR2: case SVM_EXIT_READ_DR3: 4687 case SVM_EXIT_READ_DR6: case SVM_EXIT_READ_DR7: case SVM_EXIT_READ_DR8: case SVM_EXIT_READ_DR9: 4688 case SVM_EXIT_READ_DR10: case SVM_EXIT_READ_DR11: case SVM_EXIT_READ_DR12: case SVM_EXIT_READ_DR13: 4689 case SVM_EXIT_READ_DR14: case SVM_EXIT_READ_DR15: 4690 { 4691 if (pVmcbNstGstCache->u16InterceptRdDRx & (1U << (uint16_t)(pSvmTransient->u64ExitCode - SVM_EXIT_READ_DR0))) 4692 return hmR0SvmExecVmexit(pVCpu, pCtx); 4693 return hmR0SvmExitReadDRx(pVCpu, pCtx, pSvmTransient); 4694 } 4695 4696 case SVM_EXIT_WRITE_DR0: case SVM_EXIT_WRITE_DR1: case SVM_EXIT_WRITE_DR2: case SVM_EXIT_WRITE_DR3: 4697 case SVM_EXIT_WRITE_DR6: case SVM_EXIT_WRITE_DR7: case SVM_EXIT_WRITE_DR8: case SVM_EXIT_WRITE_DR9: 4698 case SVM_EXIT_WRITE_DR10: case SVM_EXIT_WRITE_DR11: case SVM_EXIT_WRITE_DR12: case SVM_EXIT_WRITE_DR13: 4699 case SVM_EXIT_WRITE_DR14: case SVM_EXIT_WRITE_DR15: 4700 { 4701 if (pVmcbNstGstCache->u16InterceptWrDRx & (1U << (uint16_t)(pSvmTransient->u64ExitCode - SVM_EXIT_WRITE_DR0))) 4702 return hmR0SvmExecVmexit(pVCpu, pCtx); 4703 return hmR0SvmExitWriteDRx(pVCpu, pCtx, pSvmTransient); 4704 } 4705 4706 /* The exceptions not handled here are already handled individually above (as they occur more frequently). */ 4707 case SVM_EXIT_EXCEPTION_0: /*case SVM_EXIT_EXCEPTION_1:*/ case SVM_EXIT_EXCEPTION_2: 4708 /*case SVM_EXIT_EXCEPTION_3:*/ case SVM_EXIT_EXCEPTION_4: case SVM_EXIT_EXCEPTION_5: 4709 /*case SVM_EXIT_EXCEPTION_6:*/ /*case SVM_EXIT_EXCEPTION_7:*/ case SVM_EXIT_EXCEPTION_8: 4710 case SVM_EXIT_EXCEPTION_9: case SVM_EXIT_EXCEPTION_10: case SVM_EXIT_EXCEPTION_11: 4711 case SVM_EXIT_EXCEPTION_12: case SVM_EXIT_EXCEPTION_13: /*case SVM_EXIT_EXCEPTION_14:*/ 4712 case SVM_EXIT_EXCEPTION_15: case SVM_EXIT_EXCEPTION_16: /*case SVM_EXIT_EXCEPTION_17:*/ 4713 case SVM_EXIT_EXCEPTION_18: case SVM_EXIT_EXCEPTION_19: case SVM_EXIT_EXCEPTION_20: 4714 case SVM_EXIT_EXCEPTION_21: case SVM_EXIT_EXCEPTION_22: case SVM_EXIT_EXCEPTION_23: 4715 case SVM_EXIT_EXCEPTION_24: case SVM_EXIT_EXCEPTION_25: case SVM_EXIT_EXCEPTION_26: 4716 case SVM_EXIT_EXCEPTION_27: case SVM_EXIT_EXCEPTION_28: case SVM_EXIT_EXCEPTION_29: 4717 case SVM_EXIT_EXCEPTION_30: case SVM_EXIT_EXCEPTION_31: 4718 { 4719 if (pVmcbNstGstCache->u32InterceptXcpt & (1U << (uint32_t)(pSvmTransient->u64ExitCode - SVM_EXIT_EXCEPTION_0))) 4720 return hmR0SvmExecVmexit(pVCpu, pCtx); 4721 /** @todo Write hmR0SvmExitXcptGeneric! */ 4722 return VERR_NOT_IMPLEMENTED; 4723 } 4724 4725 case SVM_EXIT_XSETBV: 4726 { 4727 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_XSETBV) 4728 return hmR0SvmExecVmexit(pVCpu, pCtx); 4729 return hmR0SvmExitXsetbv(pVCpu, pCtx, pSvmTransient); 4730 } 4731 4732 case SVM_EXIT_TASK_SWITCH: 4733 { 4734 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_TASK_SWITCH) 4735 return hmR0SvmExecVmexit(pVCpu, pCtx); 4736 return hmR0SvmExitTaskSwitch(pVCpu, pCtx, pSvmTransient); 4737 } 4738 4739 case SVM_EXIT_IRET: 4740 { 4741 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_IRET) 4742 return hmR0SvmExecVmexit(pVCpu, pCtx); 4743 return hmR0SvmExitIret(pVCpu, pCtx, pSvmTransient); 4744 } 4745 4746 case SVM_EXIT_SHUTDOWN: 4747 { 4748 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_SHUTDOWN) 4749 return hmR0SvmExecVmexit(pVCpu, pCtx); 4750 return hmR0SvmExitShutdown(pVCpu, pCtx, pSvmTransient); 4751 } 4752 4753 case SVM_EXIT_SMI: 4754 { 4755 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_SMI) 4756 return hmR0SvmExecVmexit(pVCpu, pCtx); 4757 return hmR0SvmExitUnexpected(pVCpu, pCtx, pSvmTransient); 4758 } 4759 4760 case SVM_EXIT_INIT: 4761 { 4762 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_INIT) 4763 return hmR0SvmExecVmexit(pVCpu, pCtx); 4764 return hmR0SvmExitUnexpected(pVCpu, pCtx, pSvmTransient); 4765 } 4766 4767 case SVM_EXIT_VMMCALL: 4768 { 4769 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_VMMCALL) 4770 hmR0SvmExecVmexit(pVCpu, pCtx); 4771 return hmR0SvmExitVmmCall(pVCpu, pCtx, pSvmTransient); 4772 } 4773 4774 case SVM_EXIT_CLGI: 4775 { 4776 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_CLGI) 4777 hmR0SvmExecVmexit(pVCpu, pCtx); 4778 return hmR0SvmExitClgi(pVCpu, pCtx, pSvmTransient); 4779 } 4780 4781 case SVM_EXIT_STGI: 4782 { 4783 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_STGI) 4784 hmR0SvmExecVmexit(pVCpu, pCtx); 4785 return hmR0SvmExitStgi(pVCpu, pCtx, pSvmTransient); 4786 } 4787 4788 case SVM_EXIT_VMLOAD: 4789 { 4790 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_VMLOAD) 4791 hmR0SvmExecVmexit(pVCpu, pCtx); 4792 return hmR0SvmExitVmload(pVCpu, pCtx, pSvmTransient); 4793 } 4794 4795 case SVM_EXIT_VMSAVE: 4796 { 4797 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_VMSAVE) 4798 hmR0SvmExecVmexit(pVCpu, pCtx); 4799 return hmR0SvmExitVmsave(pVCpu, pCtx, pSvmTransient); 4800 } 4801 4802 case SVM_EXIT_INVLPGA: 4803 { 4804 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_INVLPGA) 4805 hmR0SvmExecVmexit(pVCpu, pCtx); 4806 return hmR0SvmExitInvlpga(pVCpu, pCtx, pSvmTransient); 4807 } 4808 4809 case SVM_EXIT_VMRUN: 4810 { 4811 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_VMRUN) 4812 hmR0SvmExecVmexit(pVCpu, pCtx); 4813 return hmR0SvmExitVmrun(pVCpu, pCtx, pSvmTransient); 4814 } 4815 4816 case SVM_EXIT_RSM: 4817 { 4818 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_RSM) 4819 hmR0SvmExecVmexit(pVCpu, pCtx); 4820 return hmR0SvmExitSetPendingXcptUD(pVCpu, pCtx, pSvmTransient); 4821 } 4822 4823 case SVM_EXIT_SKINIT: 4824 { 4825 if (pVmcbNstGstCache->u64InterceptCtrl & SVM_CTRL_INTERCEPT_SKINIT) 4826 hmR0SvmExecVmexit(pVCpu, pCtx); 4827 return hmR0SvmExitSetPendingXcptUD(pVCpu, pCtx, pSvmTransient); 4828 } 4829 4830 case SVM_EXIT_NPF: 4831 { 4832 /* We don't yet support nested-paging for nested-guests, so this should never really happen. */ 4833 Assert(!pVmcbNstGstCtrl->NestedPaging.n.u1NestedPaging); 4834 return hmR0SvmExitUnexpected(pVCpu, pCtx, pSvmTransient); 4835 } 4836 4837 default: 4838 { 4839 AssertMsgFailed(("hmR0SvmHandleExitNested: Unknown exit code %#x\n", pSvmTransient->u64ExitCode)); 4840 pVCpu->hm.s.u32HMError = pSvmTransient->u64ExitCode; 4841 return VERR_SVM_UNKNOWN_EXIT; 4842 } 4843 } 4844 } 4845 } 4846 /* not reached */ 4847 4848 #undef HM_SVM_HANDLE_XCPT_EXIT_NESTED 4849 } 4850 #endif 4851 4852 4853 /** 4854 * Handles a guest \#VMEXIT (for all EXITCODE values except SVM_EXIT_INVALID). 4855 * 4856 * @returns VBox status code (informational status codes included). 4857 * @param pVCpu The cross context virtual CPU structure. 4858 * @param pCtx Pointer to the guest-CPU context. 4859 * @param pSvmTransient Pointer to the SVM transient structure. 4860 */ 4861 static int hmR0SvmHandleExit(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMTRANSIENT pSvmTransient) 4862 { 4863 Assert(pSvmTransient->u64ExitCode != SVM_EXIT_INVALID); 4864 Assert(pSvmTransient->u64ExitCode <= SVM_EXIT_MAX); 4865 4866 /* 4867 * The ordering of the case labels is based on most-frequently-occurring #VMEXITs for most guests under 4868 * normal workloads (for some definition of "normal"). 4869 */ 4870 uint32_t u32ExitCode = pSvmTransient->u64ExitCode; 4871 switch (pSvmTransient->u64ExitCode) 4872 { 4873 case SVM_EXIT_NPF: 4874 return hmR0SvmExitNestedPF(pVCpu, pCtx, pSvmTransient); 4875 4876 case SVM_EXIT_IOIO: 4877 return hmR0SvmExitIOInstr(pVCpu, pCtx, pSvmTransient); 4878 4879 case SVM_EXIT_RDTSC: 4880 return hmR0SvmExitRdtsc(pVCpu, pCtx, pSvmTransient); 4881 4882 case SVM_EXIT_RDTSCP: 4883 return hmR0SvmExitRdtscp(pVCpu, pCtx, pSvmTransient); 4884 4885 case SVM_EXIT_CPUID: 4886 return hmR0SvmExitCpuid(pVCpu, pCtx, pSvmTransient); 4887 4888 case SVM_EXIT_EXCEPTION_14: /* X86_XCPT_PF */ 4889 return hmR0SvmExitXcptPF(pVCpu, pCtx, pSvmTransient); 4890 4891 case SVM_EXIT_EXCEPTION_7: /* X86_XCPT_NM */ 4892 return hmR0SvmExitXcptNM(pVCpu, pCtx, pSvmTransient); 4893 4894 case SVM_EXIT_EXCEPTION_6: /* X86_XCPT_UD */ 4895 return hmR0SvmExitXcptUD(pVCpu, pCtx, pSvmTransient); 4896 4897 case SVM_EXIT_EXCEPTION_16: /* X86_XCPT_MF */ 4898 return hmR0SvmExitXcptMF(pVCpu, pCtx, pSvmTransient); 4899 4900 case SVM_EXIT_EXCEPTION_1: /* X86_XCPT_DB */ 4901 return hmR0SvmExitXcptDB(pVCpu, pCtx, pSvmTransient); 4902 4903 case SVM_EXIT_EXCEPTION_17: /* X86_XCPT_AC */ 4904 return hmR0SvmExitXcptAC(pVCpu, pCtx, pSvmTransient); 4905 4906 case SVM_EXIT_EXCEPTION_3: /* X86_XCPT_BP */ 4907 return hmR0SvmExitXcptBP(pVCpu, pCtx, pSvmTransient); 4908 4909 case SVM_EXIT_MONITOR: 4910 return hmR0SvmExitMonitor(pVCpu, pCtx, pSvmTransient); 4911 4912 case SVM_EXIT_MWAIT: 4913 return hmR0SvmExitMwait(pVCpu, pCtx, pSvmTransient); 4914 4915 case SVM_EXIT_HLT: 4916 return hmR0SvmExitHlt(pVCpu, pCtx, pSvmTransient); 4917 4918 case SVM_EXIT_READ_CR0: 4919 case SVM_EXIT_READ_CR3: 4920 case SVM_EXIT_READ_CR4: 4921 return hmR0SvmExitReadCRx(pVCpu, pCtx, pSvmTransient); 4922 4923 case SVM_EXIT_WRITE_CR0: 4924 case SVM_EXIT_WRITE_CR3: 4925 case SVM_EXIT_WRITE_CR4: 4926 case SVM_EXIT_WRITE_CR8: 4927 return hmR0SvmExitWriteCRx(pVCpu, pCtx, pSvmTransient); 4489 4928 4490 4929 case SVM_EXIT_PAUSE: … … 4501 4940 case SVM_EXIT_NMI: 4502 4941 return hmR0SvmExitIntr(pVCpu, pCtx, pSvmTransient); 4942 4943 case SVM_EXIT_MSR: 4944 return hmR0SvmExitMsr(pVCpu, pCtx, pSvmTransient); 4503 4945 4504 4946 case SVM_EXIT_INVLPG: … … 4546 4988 { 4547 4989 /* 4548 * We don't intercept NMIs. As for INIT signals, it really shouldn't ever happen here. If it ever does,4549 * we want to know about it so log the exit code and bail.4990 * We don't intercept SMIs. As for INIT signals, it really shouldn't ever happen here. 4991 * If it ever does, we want to know about it so log the exit code and bail. 4550 4992 */ 4551 AssertMsgFailed(("hmR0SvmHandleExitNested: Unexpected exit %#RX32\n", (uint32_t)pSvmTransient->u64ExitCode)); 4552 pVCpu->hm.s.u32HMError = (uint32_t)pSvmTransient->u64ExitCode; 4553 return VERR_SVM_UNEXPECTED_EXIT; 4993 return hmR0SvmExitUnexpected(pVCpu, pCtx, pSvmTransient); 4554 4994 } 4555 4995 … … 4634 5074 4635 5075 default: 4636 AssertMsgFailed(("hmR0SvmHandleExitNested: Unexpected exit caused by exception %#x\n", Event.n.u8Vector));4637 pVCpu->hm.s.u32HMError = Event.n.u8Vector;4638 return VERR_SVM_UNEXPECTED_XCPT_EXIT;4639 }4640 4641 Log4(("#Xcpt: Vector=%#x at CS:RIP=%04x:%RGv\n", Event.n.u8Vector, pCtx->cs.Sel, (RTGCPTR)pCtx->rip));4642 hmR0SvmSetPendingEvent(pVCpu, &Event, 0 /* GCPtrFaultAddress */);4643 return VINF_SUCCESS;4644 }4645 #endif /* HMSVM_ALWAYS_TRAP_ALL_XCPTS */4646 4647 default:4648 {4649 AssertMsgFailed(("hmR0SvmHandleExitNested: Unknown exit code %#x\n", pSvmTransient->u64ExitCode));4650 pVCpu->hm.s.u32HMError = pSvmTransient->u64ExitCode;4651 return VERR_SVM_UNKNOWN_EXIT;4652 }4653 }4654 }4655 }4656 /* not reached */4657 4658 #undef HM_SVM_HANDLE_XCPT_EXIT_NESTED4659 }4660 #endif4661 4662 4663 /**4664 * Handles a guest \#VMEXIT (for all EXITCODE values except SVM_EXIT_INVALID).4665 *4666 * @returns VBox status code (informational status codes included).4667 * @param pVCpu The cross context virtual CPU structure.4668 * @param pCtx Pointer to the guest-CPU context.4669 * @param pSvmTransient Pointer to the SVM transient structure.4670 */4671 static int hmR0SvmHandleExit(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMTRANSIENT pSvmTransient)4672 {4673 Assert(pSvmTransient->u64ExitCode != SVM_EXIT_INVALID);4674 Assert(pSvmTransient->u64ExitCode <= SVM_EXIT_MAX);4675 4676 /*4677 * The ordering of the case labels is based on most-frequently-occurring #VMEXITs for most guests under4678 * normal workloads (for some definition of "normal").4679 */4680 uint32_t u32ExitCode = pSvmTransient->u64ExitCode;4681 switch (pSvmTransient->u64ExitCode)4682 {4683 case SVM_EXIT_NPF:4684 return hmR0SvmExitNestedPF(pVCpu, pCtx, pSvmTransient);4685 4686 case SVM_EXIT_IOIO:4687 return hmR0SvmExitIOInstr(pVCpu, pCtx, pSvmTransient);4688 4689 case SVM_EXIT_RDTSC:4690 return hmR0SvmExitRdtsc(pVCpu, pCtx, pSvmTransient);4691 4692 case SVM_EXIT_RDTSCP:4693 return hmR0SvmExitRdtscp(pVCpu, pCtx, pSvmTransient);4694 4695 case SVM_EXIT_CPUID:4696 return hmR0SvmExitCpuid(pVCpu, pCtx, pSvmTransient);4697 4698 case SVM_EXIT_EXCEPTION_14: /* X86_XCPT_PF */4699 return hmR0SvmExitXcptPF(pVCpu, pCtx, pSvmTransient);4700 4701 case SVM_EXIT_EXCEPTION_7: /* X86_XCPT_NM */4702 return hmR0SvmExitXcptNM(pVCpu, pCtx, pSvmTransient);4703 4704 case SVM_EXIT_EXCEPTION_6: /* X86_XCPT_UD */4705 return hmR0SvmExitXcptUD(pVCpu, pCtx, pSvmTransient);4706 4707 case SVM_EXIT_EXCEPTION_16: /* X86_XCPT_MF */4708 return hmR0SvmExitXcptMF(pVCpu, pCtx, pSvmTransient);4709 4710 case SVM_EXIT_EXCEPTION_1: /* X86_XCPT_DB */4711 return hmR0SvmExitXcptDB(pVCpu, pCtx, pSvmTransient);4712 4713 case SVM_EXIT_EXCEPTION_17: /* X86_XCPT_AC */4714 return hmR0SvmExitXcptAC(pVCpu, pCtx, pSvmTransient);4715 4716 case SVM_EXIT_EXCEPTION_3: /* X86_XCPT_BP */4717 return hmR0SvmExitXcptBP(pVCpu, pCtx, pSvmTransient);4718 4719 case SVM_EXIT_MONITOR:4720 return hmR0SvmExitMonitor(pVCpu, pCtx, pSvmTransient);4721 4722 case SVM_EXIT_MWAIT:4723 return hmR0SvmExitMwait(pVCpu, pCtx, pSvmTransient);4724 4725 case SVM_EXIT_HLT:4726 return hmR0SvmExitHlt(pVCpu, pCtx, pSvmTransient);4727 4728 case SVM_EXIT_READ_CR0:4729 case SVM_EXIT_READ_CR3:4730 case SVM_EXIT_READ_CR4:4731 return hmR0SvmExitReadCRx(pVCpu, pCtx, pSvmTransient);4732 4733 case SVM_EXIT_WRITE_CR0:4734 case SVM_EXIT_WRITE_CR3:4735 case SVM_EXIT_WRITE_CR4:4736 case SVM_EXIT_WRITE_CR8:4737 return hmR0SvmExitWriteCRx(pVCpu, pCtx, pSvmTransient);4738 4739 case SVM_EXIT_PAUSE:4740 return hmR0SvmExitPause(pVCpu, pCtx, pSvmTransient);4741 4742 case SVM_EXIT_VMMCALL:4743 return hmR0SvmExitVmmCall(pVCpu, pCtx, pSvmTransient);4744 4745 case SVM_EXIT_VINTR:4746 return hmR0SvmExitVIntr(pVCpu, pCtx, pSvmTransient);4747 4748 case SVM_EXIT_INTR:4749 case SVM_EXIT_FERR_FREEZE:4750 case SVM_EXIT_NMI:4751 return hmR0SvmExitIntr(pVCpu, pCtx, pSvmTransient);4752 4753 case SVM_EXIT_MSR:4754 return hmR0SvmExitMsr(pVCpu, pCtx, pSvmTransient);4755 4756 case SVM_EXIT_INVLPG:4757 return hmR0SvmExitInvlpg(pVCpu, pCtx, pSvmTransient);4758 4759 case SVM_EXIT_WBINVD:4760 return hmR0SvmExitWbinvd(pVCpu, pCtx, pSvmTransient);4761 4762 case SVM_EXIT_INVD:4763 return hmR0SvmExitInvd(pVCpu, pCtx, pSvmTransient);4764 4765 case SVM_EXIT_RDPMC:4766 return hmR0SvmExitRdpmc(pVCpu, pCtx, pSvmTransient);4767 4768 default:4769 {4770 switch (pSvmTransient->u64ExitCode)4771 {4772 case SVM_EXIT_READ_DR0: case SVM_EXIT_READ_DR1: case SVM_EXIT_READ_DR2: case SVM_EXIT_READ_DR3:4773 case SVM_EXIT_READ_DR6: case SVM_EXIT_READ_DR7: case SVM_EXIT_READ_DR8: case SVM_EXIT_READ_DR9:4774 case SVM_EXIT_READ_DR10: case SVM_EXIT_READ_DR11: case SVM_EXIT_READ_DR12: case SVM_EXIT_READ_DR13:4775 case SVM_EXIT_READ_DR14: case SVM_EXIT_READ_DR15:4776 return hmR0SvmExitReadDRx(pVCpu, pCtx, pSvmTransient);4777 4778 case SVM_EXIT_WRITE_DR0: case SVM_EXIT_WRITE_DR1: case SVM_EXIT_WRITE_DR2: case SVM_EXIT_WRITE_DR3:4779 case SVM_EXIT_WRITE_DR6: case SVM_EXIT_WRITE_DR7: case SVM_EXIT_WRITE_DR8: case SVM_EXIT_WRITE_DR9:4780 case SVM_EXIT_WRITE_DR10: case SVM_EXIT_WRITE_DR11: case SVM_EXIT_WRITE_DR12: case SVM_EXIT_WRITE_DR13:4781 case SVM_EXIT_WRITE_DR14: case SVM_EXIT_WRITE_DR15:4782 return hmR0SvmExitWriteDRx(pVCpu, pCtx, pSvmTransient);4783 4784 case SVM_EXIT_XSETBV:4785 return hmR0SvmExitXsetbv(pVCpu, pCtx, pSvmTransient);4786 4787 case SVM_EXIT_TASK_SWITCH:4788 return hmR0SvmExitTaskSwitch(pVCpu, pCtx, pSvmTransient);4789 4790 case SVM_EXIT_IRET:4791 return hmR0SvmExitIret(pVCpu, pCtx, pSvmTransient);4792 4793 case SVM_EXIT_SHUTDOWN:4794 return hmR0SvmExitShutdown(pVCpu, pCtx, pSvmTransient);4795 4796 case SVM_EXIT_SMI:4797 case SVM_EXIT_INIT:4798 {4799 /*4800 * We don't intercept NMIs. As for INIT signals, it really shouldn't ever happen here. If it ever does,4801 * we want to know about it so log the exit code and bail.4802 */4803 AssertMsgFailed(("hmR0SvmHandleExit: Unexpected exit %#RX32\n", (uint32_t)pSvmTransient->u64ExitCode));4804 pVCpu->hm.s.u32HMError = (uint32_t)pSvmTransient->u64ExitCode;4805 return VERR_SVM_UNEXPECTED_EXIT;4806 }4807 4808 #ifdef VBOX_WITH_NESTED_HWVIRT4809 case SVM_EXIT_CLGI: return hmR0SvmExitClgi(pVCpu, pCtx, pSvmTransient);4810 case SVM_EXIT_STGI: return hmR0SvmExitStgi(pVCpu, pCtx, pSvmTransient);4811 case SVM_EXIT_VMLOAD: return hmR0SvmExitVmload(pVCpu, pCtx, pSvmTransient);4812 case SVM_EXIT_VMSAVE: return hmR0SvmExitVmsave(pVCpu, pCtx, pSvmTransient);4813 case SVM_EXIT_INVLPGA: return hmR0SvmExitInvlpga(pVCpu, pCtx, pSvmTransient);4814 case SVM_EXIT_VMRUN: return hmR0SvmExitVmrun(pVCpu, pCtx, pSvmTransient);4815 #else4816 case SVM_EXIT_CLGI:4817 case SVM_EXIT_STGI:4818 case SVM_EXIT_VMLOAD:4819 case SVM_EXIT_VMSAVE:4820 case SVM_EXIT_INVLPGA:4821 case SVM_EXIT_VMRUN:4822 #endif4823 case SVM_EXIT_RSM:4824 case SVM_EXIT_SKINIT:4825 return hmR0SvmExitSetPendingXcptUD(pVCpu, pCtx, pSvmTransient);4826 4827 #ifdef HMSVM_ALWAYS_TRAP_ALL_XCPTS4828 case SVM_EXIT_EXCEPTION_0: /* X86_XCPT_DE */4829 /* SVM_EXIT_EXCEPTION_1: */ /* X86_XCPT_DB - Handled above. */4830 case SVM_EXIT_EXCEPTION_2: /* X86_XCPT_NMI */4831 /* SVM_EXIT_EXCEPTION_3: */ /* X86_XCPT_BP - Handled above. */4832 case SVM_EXIT_EXCEPTION_4: /* X86_XCPT_OF */4833 case SVM_EXIT_EXCEPTION_5: /* X86_XCPT_BR */4834 /* SVM_EXIT_EXCEPTION_6: */ /* X86_XCPT_UD - Handled above. */4835 /* SVM_EXIT_EXCEPTION_7: */ /* X86_XCPT_NM - Handled above. */4836 case SVM_EXIT_EXCEPTION_8: /* X86_XCPT_DF */4837 case SVM_EXIT_EXCEPTION_9: /* X86_XCPT_CO_SEG_OVERRUN */4838 case SVM_EXIT_EXCEPTION_10: /* X86_XCPT_TS */4839 case SVM_EXIT_EXCEPTION_11: /* X86_XCPT_NP */4840 case SVM_EXIT_EXCEPTION_12: /* X86_XCPT_SS */4841 case SVM_EXIT_EXCEPTION_13: /* X86_XCPT_GP */4842 /* SVM_EXIT_EXCEPTION_14: */ /* X86_XCPT_PF - Handled above. */4843 case SVM_EXIT_EXCEPTION_15: /* Reserved. */4844 /* SVM_EXIT_EXCEPTION_16: */ /* X86_XCPT_MF - Handled above. */4845 /* SVM_EXIT_EXCEPTION_17: */ /* X86_XCPT_AC - Handled above. */4846 case SVM_EXIT_EXCEPTION_18: /* X86_XCPT_MC */4847 case SVM_EXIT_EXCEPTION_19: /* X86_XCPT_XF */4848 case SVM_EXIT_EXCEPTION_20: case SVM_EXIT_EXCEPTION_21: case SVM_EXIT_EXCEPTION_22:4849 case SVM_EXIT_EXCEPTION_23: case SVM_EXIT_EXCEPTION_24: case SVM_EXIT_EXCEPTION_25:4850 case SVM_EXIT_EXCEPTION_26: case SVM_EXIT_EXCEPTION_27: case SVM_EXIT_EXCEPTION_28:4851 case SVM_EXIT_EXCEPTION_29: case SVM_EXIT_EXCEPTION_30: case SVM_EXIT_EXCEPTION_31:4852 {4853 /** @todo r=ramshankar; We should be doing4854 * HMSVM_CHECK_EXIT_DUE_TO_EVENT_DELIVERY here! */4855 4856 PSVMVMCB pVmcb = pVCpu->hm.s.svm.pVmcb;4857 SVMEVENT Event;4858 Event.u = 0;4859 Event.n.u1Valid = 1;4860 Event.n.u3Type = SVM_EVENT_EXCEPTION;4861 Event.n.u8Vector = pSvmTransient->u64ExitCode - SVM_EXIT_EXCEPTION_0;4862 4863 switch (Event.n.u8Vector)4864 {4865 case X86_XCPT_DE:4866 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE);4867 break;4868 4869 case X86_XCPT_NP:4870 Event.n.u1ErrorCodeValid = 1;4871 Event.n.u32ErrorCode = pVmcb->ctrl.u64ExitInfo1;4872 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP);4873 break;4874 4875 case X86_XCPT_SS:4876 Event.n.u1ErrorCodeValid = 1;4877 Event.n.u32ErrorCode = pVmcb->ctrl.u64ExitInfo1;4878 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS);4879 break;4880 4881 case X86_XCPT_GP:4882 Event.n.u1ErrorCodeValid = 1;4883 Event.n.u32ErrorCode = pVmcb->ctrl.u64ExitInfo1;4884 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);4885 break;4886 4887 default:4888 5076 AssertMsgFailed(("hmR0SvmHandleExit: Unexpected exit caused by exception %#x\n", Event.n.u8Vector)); 4889 5077 pVCpu->hm.s.u32HMError = Event.n.u8Vector; … … 5012 5200 } 5013 5201 5014 5015 /**5016 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.5017 *5018 * @param pVCpu The cross context virtual CPU structure.5019 */5020 DECLINLINE(void) hmR0SvmSetPendingXcptUD(PVMCPU pVCpu)5021 {5022 SVMEVENT Event;5023 Event.u = 0;5024 Event.n.u1Valid = 1;5025 Event.n.u3Type = SVM_EVENT_EXCEPTION;5026 Event.n.u8Vector = X86_XCPT_UD;5027 hmR0SvmSetPendingEvent(pVCpu, &Event, 0 /* GCPtrFaultAddress */);5028 }5029 5030 5031 /**5032 * Sets a debug (\#DB) exception as pending-for-injection into the VM.5033 *5034 * @param pVCpu The cross context virtual CPU structure.5035 */5036 DECLINLINE(void) hmR0SvmSetPendingXcptDB(PVMCPU pVCpu)5037 {5038 SVMEVENT Event;5039 Event.u = 0;5040 Event.n.u1Valid = 1;5041 Event.n.u3Type = SVM_EVENT_EXCEPTION;5042 Event.n.u8Vector = X86_XCPT_DB;5043 hmR0SvmSetPendingEvent(pVCpu, &Event, 0 /* GCPtrFaultAddress */);5044 }5045 5046 5047 /**5048 * Sets a page fault (\#PF) exception as pending-for-injection into the VM.5049 *5050 * @param pVCpu The cross context virtual CPU structure.5051 * @param pCtx Pointer to the guest-CPU context.5052 * @param u32ErrCode The error-code for the page-fault.5053 * @param uFaultAddress The page fault address (CR2).5054 *5055 * @remarks This updates the guest CR2 with @a uFaultAddress!5056 */5057 DECLINLINE(void) hmR0SvmSetPendingXcptPF(PVMCPU pVCpu, PCPUMCTX pCtx, uint32_t u32ErrCode, RTGCUINTPTR uFaultAddress)5058 {5059 SVMEVENT Event;5060 Event.u = 0;5061 Event.n.u1Valid = 1;5062 Event.n.u3Type = SVM_EVENT_EXCEPTION;5063 Event.n.u8Vector = X86_XCPT_PF;5064 Event.n.u1ErrorCodeValid = 1;5065 Event.n.u32ErrorCode = u32ErrCode;5066 5067 /* Update CR2 of the guest. */5068 if (pCtx->cr2 != uFaultAddress)5069 {5070 pCtx->cr2 = uFaultAddress;5071 HMCPU_CF_SET(pVCpu, HM_CHANGED_GUEST_CR2);5072 }5073 5074 hmR0SvmSetPendingEvent(pVCpu, &Event, uFaultAddress);5075 }5076 5077 5078 /**5079 * Sets a device-not-available (\#NM) exception as pending-for-injection into5080 * the VM.5081 *5082 * @param pVCpu The cross context virtual CPU structure.5083 */5084 DECLINLINE(void) hmR0SvmSetPendingXcptNM(PVMCPU pVCpu)5085 {5086 SVMEVENT Event;5087 Event.u = 0;5088 Event.n.u1Valid = 1;5089 Event.n.u3Type = SVM_EVENT_EXCEPTION;5090 Event.n.u8Vector = X86_XCPT_NM;5091 hmR0SvmSetPendingEvent(pVCpu, &Event, 0 /* GCPtrFaultAddress */);5092 }5093 5094 5095 /**5096 * Sets a math-fault (\#MF) exception as pending-for-injection into the VM.5097 *5098 * @param pVCpu The cross context virtual CPU structure.5099 */5100 DECLINLINE(void) hmR0SvmSetPendingXcptMF(PVMCPU pVCpu)5101 {5102 SVMEVENT Event;5103 Event.u = 0;5104 Event.n.u1Valid = 1;5105 Event.n.u3Type = SVM_EVENT_EXCEPTION;5106 Event.n.u8Vector = X86_XCPT_MF;5107 hmR0SvmSetPendingEvent(pVCpu, &Event, 0 /* GCPtrFaultAddress */);5108 }5109 5110 5111 /**5112 * Sets a double fault (\#DF) exception as pending-for-injection into the VM.5113 *5114 * @param pVCpu The cross context virtual CPU structure.5115 */5116 DECLINLINE(void) hmR0SvmSetPendingXcptDF(PVMCPU pVCpu)5117 {5118 SVMEVENT Event;5119 Event.u = 0;5120 Event.n.u1Valid = 1;5121 Event.n.u3Type = SVM_EVENT_EXCEPTION;5122 Event.n.u8Vector = X86_XCPT_DF;5123 Event.n.u1ErrorCodeValid = 1;5124 Event.n.u32ErrorCode = 0;5125 hmR0SvmSetPendingEvent(pVCpu, &Event, 0 /* GCPtrFaultAddress */);5126 }5127 5202 5128 5203 #ifdef HMSVM_USE_IEM_EVENT_REFLECTION … … 6160 6235 6161 6236 /** 6237 * \#VMEXIT handler for unexpected exits. Conditional \#VMEXIT. 6238 */ 6239 HMSVM_EXIT_DECL hmR0SvmExitUnexpected(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMTRANSIENT pSvmTransient) 6240 { 6241 RT_NOREF(pCtx); 6242 AssertMsgFailed(("hmR0SvmExitUnexpected: ExitCode=%#RX64\n", pSvmTransient->u64ExitCode)); 6243 pVCpu->hm.s.u32HMError = (uint32_t)pSvmTransient->u64ExitCode; 6244 return VERR_SVM_UNEXPECTED_EXIT; 6245 } 6246 6247 6248 /** 6162 6249 * \#VMEXIT handler for CRx reads (SVM_EXIT_READ_CR*). Conditional \#VMEXIT. 6163 6250 */
Note:
See TracChangeset
for help on using the changeset viewer.