Changeset 46603 in vbox
- Timestamp:
- Jun 17, 2013 4:31:02 PM (12 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
r46594 r46603 538 538 #endif 539 539 #ifdef HMSVM_ALWAYS_TRAP_ALL_XCPTS 540 /* If you add any exceptions here, make sure to update hmR0SvmHandleExit(). */ 540 541 pVmcb->ctrl.u32InterceptException |= RT_BIT(X86_XCPT_BP) 541 542 | RT_BIT(X86_XCPT_DB) … … 2646 2647 switch (pSvmTransient->u64ExitCode) 2647 2648 { 2648 /** @todo */2649 //SVM_EXIT_EXCEPTION_x:2650 2651 2649 case SVM_EXIT_NPF: 2652 2650 return hmR0SvmExitNestedPF(pVCpu, pCtx, pSvmTransient); … … 2663 2661 case SVM_EXIT_CPUID: 2664 2662 return hmR0SvmExitCpuid(pVCpu, pCtx, pSvmTransient); 2663 2664 case SVM_EXIT_EXCEPTION_E: /* X86_XCPT_PF */ 2665 return hmR0SvmExitXcptPF(pVCpu, pCtx, pSvmTransient); 2666 2667 case SVM_EXIT_EXCEPTION_7: /* X86_XCPT_NM */ 2668 return hmR0SvmExitXcptNM(pVCpu, pCtx, pSvmTransient); 2669 2670 case SVM_EXIT_EXCEPTION_10: /* X86_XCPT_MF */ 2671 return hmR0SvmExitXcptMF(pVCpu, pCtx, pSvmTransient); 2672 2673 case SVM_EXIT_EXCEPTION_1: /* X86_XCPT_DB */ 2674 return hmR0SvmExitXcptDB(pVCpu, pCtx, pSvmTransient); 2665 2675 2666 2676 case SVM_EXIT_MONITOR: … … 2734 2744 case SVM_EXIT_SKINIT: 2735 2745 return hmR0SvmExitSetPendingXcptUD(pVCpu, pCtx, pSvmTransient); 2746 2747 #ifdef HMSVM_ALWAYS_TRAP_ALL_XCPTS 2748 case SVM_EXIT_EXCEPTION_0: /* X86_XCPT_DE */ 2749 case SVM_EXIT_EXCEPTION_3: /* X86_XCPT_BP */ 2750 case SVM_EXIT_EXCEPTION_6: /* X86_XCPT_UD */ 2751 case SVM_EXIT_EXCEPTION_B: /* X86_XCPT_NP */ 2752 case SVM_EXIT_EXCEPTION_C: /* X86_XCPT_SS */ 2753 case SVM_EXIT_EXCEPTION_D: /* X86_XCPT_GP */ 2754 return 2755 #endif 2736 2756 2737 2757 default: … … 2881 2901 2882 2902 /** 2903 * Sets a page fault (#PF) exception as pending-for-injection into the VM. 2904 * 2905 * @param pVCpu Pointer to the VMCPU. 2906 * @param pCtx Pointer to the guest-CPU context. 2907 * @param u32ErrCode The error-code for the page-fault. 2908 * @param uFaultAddress The page fault address (CR2). 2909 * 2910 * @remarks This updates the guest CR2 with @a uFaultAddress! 2911 */ 2912 DECLINLINE(void) hmR0SvmSetPendingXcptPF(PVMCPU pVCpu, PCPUMCTX pCtx, uint32_t u32ErrCode, RTGCUINTPTR uFaultAddress) 2913 { 2914 SVMEVENT Event; 2915 Event.u = 0; 2916 Event.n.u1Valid = 1; 2917 Event.n.u3Type = SVM_EVENT_EXCEPTION; 2918 Event.n.u8Vector = X86_XCPT_PF; 2919 Event.n.u1ErrorCodeValid = 1; 2920 Event.n.u32ErrorCode = u32ErrCode; 2921 2922 /* Update CR2 of the guest. */ 2923 pCtx->cr2 = uFaultAddress; 2924 2925 hmR0SvmSetPendingEvent(pVCpu, &Event); 2926 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); 2927 } 2928 2929 2930 /** 2931 * Sets a device-not-available (#NM) exception as pending-for-injection into the 2932 * VM. 2933 * 2934 * @param pVCpu Pointer to the VMCPU. 2935 */ 2936 DECLINLINE(void) hmR0SvmSetPendingXcptNM(PVMCPU pVCpu) 2937 { 2938 SVMEVENT Event; 2939 Event.u = 0; 2940 Event.n.u1Valid = 1; 2941 Event.n.u3Type = SVM_EVENT_EXCEPTION; 2942 Event.n.u8Vector = X86_XCPT_NM; 2943 hmR0SvmSetPendingEvent(pVCpu, &Event); 2944 } 2945 2946 2947 /** 2948 * Sets a math-fault (#MF) exception as pending-for-injection into the VM. 2949 * 2950 * @param pVCpu Pointer to the VMCPU. 2951 */ 2952 DECLINLINE(void) hmR0SvmSetPendingXcptMF(PVMCPU pVCpu) 2953 { 2954 SVMEVENT Event; 2955 Event.u = 0; 2956 Event.n.u1Valid = 1; 2957 Event.n.u3Type = SVM_EVENT_EXCEPTION; 2958 Event.n.u8Vector = X86_XCPT_MF; 2959 hmR0SvmSetPendingEvent(pVCpu, &Event); 2960 } 2961 2962 2963 /** 2883 2964 * Emulates a simple MOV TPR (CR8) instruction, used for TPR patching on 32-bit 2884 2965 * guests. This simply looks up the patch record at EIP and does the required. … … 3666 3747 3667 3748 3749 /** 3750 * #VMEXIT handler for page faults (SVM_EXIT_PF). Conditional #VMEXIT. 3751 */ 3752 HMSVM_EXIT_DECL hmR0SvmExitXcptPF(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMTRANSIENT pSvmTransient) 3753 { 3754 HMSVM_VALIDATE_EXIT_HANDLER_PARAMS(); 3755 3756 /* -XXX- @todo Vectoring pagefaults!! */ 3757 3758 /* See AMD spec. 15.12.15 "#PF (Page Fault)". */ 3759 PSVMVMCB pVmcb = (PSVMVMCB)pVCpu->hm.s.svm.pvVmcb; 3760 uint32_t u32ErrCode = pVmcb->ctrl.u64ExitInfo1; 3761 RTGCUINTPTR uFaultAddress = pVmcb->ctrl.u64ExitInfo2; 3762 3763 #if defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) || defined(HMVMX_ALWAYS_TRAP_PF) 3764 if (pVM->hm.s.fNestedPaging) 3765 { 3766 /* A genuine guest #PF, reflect it to the guest. */ 3767 Log4(("#PF: Guest page fault at %04X:%RGv FaultAddr=%RGv ErrCode=%#x\n", pCtx->cs, (RTGCPTR)pCtx->rip, uFaultAddress, 3768 u32ErrCode)); 3769 hmR0SvmSetPendingXcptPF(pVCpu, pCtx, u32ErrCode, uFaultAddress); 3770 return VINF_SUCCESS; 3771 } 3772 #endif 3773 3774 Assert(!pVM->hm.s.fNestedPaging); 3775 3776 #ifdef VBOX_HM_WITH_GUEST_PATCHING 3777 /* Shortcut for APIC TPR reads and writes; only applicable to 32-bit guests. */ 3778 if ( pVM->hm.s.fTRPPatchingAllowed 3779 && (uFaultAddress & 0xfff) == 0x80 /* TPR offset. */ 3780 && !(u32ErrCode & X86_TRAP_PF_P) /* Not present */ 3781 && !CPUMGetGuestCPL(pVCpu) 3782 && !CPUMIsGuestInLongModeEx(pCtx) 3783 && pVM->hm.s.cPatches < RT_ELEMENTS(pVM->hm.s.aPatches)) 3784 { 3785 RTGCPHYS GCPhysApicBase; 3786 GCPhysApicBase = pCtx->msrApicBase; 3787 GCPhysApicBase &= PAGE_BASE_GC_MASK; 3788 3789 /* Check if the page at the fault-address is the APIC base. */ 3790 RTGCPHYS GCPhysPage; 3791 rc = PGMGstGetPage(pVCpu, (RTGCPTR)uFaultAddress, NULL /* pfFlags */, &GCPhysPage); 3792 if ( rc == VINF_SUCCESS 3793 && GCPhys == GCPhysApicBase) 3794 { 3795 /* Only attempt to patch the instruction once. */ 3796 PHMTPRPATCH pPatch = (PHMTPRPATCH)RTAvloU32Get(&pVM->hm.s.PatchTree, (AVLOU32KEY)pCtx->eip); 3797 if (!pPatch) 3798 return VINF_EM_HM_PATCH_TPR_INSTR; 3799 } 3800 } 3801 #endif 3802 3803 Log4(("#PF: uFaultAddress=%#RX64 cs:rip=%#04x:%#RX64 u32ErrCode %#RX32 cr3=%#RX64\n", uFaultAddress, pCtx->cs.Sel, 3804 pCtx->rip, u32ErrCode, pCtx->cr3)); 3805 3806 TRPMAssertXcptPF(pVCpu, uFaultAddress, u32ErrCode); 3807 int rc = PGMTrap0eHandler(pVCpu, errCode, CPUMCTX2CORE(pCtx), (RTGCPTR)uFaultAddress); 3808 3809 Log2(("#PF rc=%Rrc\n", rc)); 3810 if (rc == VINF_SUCCESS) 3811 { 3812 /* Successfully synced shadow pages tables or emulated an MMIO instruction. */ 3813 TRPMResetTrap(pVCpu); 3814 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF); 3815 return rc; 3816 } 3817 else if (rc == VINF_EM_RAW_GUEST_TRAP) 3818 { 3819 /* It's a guest page fault and needs to be reflected to the guest. */ 3820 3821 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); 3822 u32ErrCode = TRPMGetErrorCode(pVCpu); /* The error code might have been changed. */ 3823 TRPMResetTrap(pVCpu); 3824 3825 hmR0SvmSetPendingXcptPF(pVCpu, pCtx, u32ErrCode, uFaultAddress); 3826 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); 3827 return VINF_SUCCESS; 3828 } 3829 3830 TRPMResetTrap(pVCpu); 3831 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM); 3832 return rc; 3833 } 3834 3835 3836 /** 3837 * #VMEXIT handler for device-not-available exception (SVM_EXIT_NM). Conditional 3838 * #VMEXIT. 3839 */ 3840 HMSVM_EXIT_DECL hmR0SvmExitXcptNM(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMTRANSIENT pSvmTransient) 3841 { 3842 HMSVM_VALIDATE_EXIT_HANDLER_PARAMS(); 3843 3844 #ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS 3845 Assert(!CPUMIsGuestFPUStateActive(pVCpu)); 3846 #endif 3847 3848 /* Lazy FPU loading; load the guest-FPU state transparently and continue execution of the guest. */ 3849 PVM pVM = pVCpu->CTX_SUFF(pVM); 3850 rc = CPUMR0LoadGuestFPU(pVM, pVCpu, pCtx); 3851 if (rc == VINF_SUCCESS) 3852 { 3853 Assert(CPUMIsGuestFPUStateActive(pVCpu)); 3854 pVCpu->hm.s.fContextUseFlags |= HM_CHANGED_GUEST_CR0; 3855 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowNM); 3856 return VINF_SUCCESS; 3857 } 3858 3859 /* Forward #NM to the guest. */ 3860 Assert(rc == VINF_EM_RAW_GUEST_TRAP); 3861 hmR0SvmSetPendingXcptNM(pVCpu); 3862 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNM); 3863 return VINF_SUCCESS; 3864 } 3865 3866 3867 /** 3868 * #VMEXIT handler for math-fault (SVM_EXIT_MF). Conditional #VMEXIT. 3869 */ 3870 HMSVM_EXIT_DECL hmR0SvmExitXcptMF(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMTRANSIENT pSvmTransient) 3871 { 3872 int rc; 3873 if (!(pMixedCtx->cr0 & X86_CR0_NE)) 3874 { 3875 /* Old-style FPU error reporting needs some extra work. */ 3876 /** @todo don't fall back to the recompiler, but do it manually. */ 3877 rc = VERR_EM_INTERPRETER; 3878 } 3879 else 3880 { 3881 hmR0SvmSetPendingXcptMF(pVCpu); 3882 rc = VINF_SUCCESS; 3883 } 3884 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); 3885 return rc; 3886 } 3887 -
trunk/src/VBox/VMM/include/HMInternal.h
r46531 r46603 130 130 /* AMD-V specific state. */ 131 131 # define HM_CHANGED_SVM_GUEST_APIC_STATE RT_BIT(16) 132 # define HM_CHANGED_SVM_ RESERVED1RT_BIT(17)132 # define HM_CHANGED_SVM_GUEST_EFER_MSR RT_BIT(17) 133 133 # define HM_CHANGED_SVM_RESERVED2 RT_BIT(18) 134 134 # define HM_CHANGED_SVM_RESERVED3 RT_BIT(19)
Note:
See TracChangeset
for help on using the changeset viewer.