Changeset 46470 in vbox
- Timestamp:
- Jun 10, 2013 3:14:27 PM (12 years ago)
- svn:sync-xref-src-repo-rev:
- 86313
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
r46444 r46470 65 65 pCtx->reg.Attr.u = HMSVM_VMCB_2_CPU_SEG_ATTR(pVmcb->guest.REG.u16Attr); \ 66 66 } while (0) 67 /** @} */ 67 /** @} */ 68 69 /** @name VMCB Clean Bits used for VMCB-state caching. */ 70 /** All intercepts vectors, TSC offset, PAUSE filter counter. */ 71 #define HMSVM_VMCB_CLEAN_INTERCEPTS RT_BIT(0) 72 /** I/O permission bitmap, MSR permission bitmap. */ 73 #define HMSVM_VMCB_CLEAN_IOPM_MSRPM RT_BIT(1) 74 /** ASID. */ 75 #define HMSVM_VMCB_CLEAN_ASID RT_BIT(2) 76 /** TRP: V_TPR, V_IRQ, V_INTR_PRIO, V_IGN_TPR, V_INTR_MASKING, 77 V_INTR_VECTOR. */ 78 #define HMSVM_VMCB_CLEAN_TPR RT_BIT(3) 79 /** Nested Paging: Nested CR3 (nCR3), PAT. */ 80 #define HMSVM_VMCB_CLEAN_NP RT_BIT(4) 81 /** Control registers (CR0, CR3, CR4, EFER). */ 82 #define HMSVM_VMCB_CLEAN_CRX RT_BIT(5) 83 /** Debug registers (DR6, DR7). */ 84 #define HMSVM_VMCB_CLEAN_DRX RT_BIT(6) 85 /** GDT, IDT limit and base. */ 86 #define HMSVM_VMCB_CLEAN_DT RT_BIT(7) 87 /** Segment register: CS, SS, DS, ES limit and base. */ 88 #define HMSVM_VMCB_CLEAN_SEG RT_BIT(8) 89 /** CR2.*/ 90 #define HMSVM_VMCB_CLEAN_CR2 RT_BIT(9) 91 /** Last-branch record (DbgCtlMsr, br_from, br_to, lastint_from, lastint_to) */ 92 #define HMSVM_VMCB_CLEAN_LBR RT_BIT(10) 93 /** AVIC (AVIC APIC_BAR; AVIC APIC_BACKING_PAGE, AVIC 94 PHYSICAL_TABLE and AVIC LOGICAL_TABLE Pointers). */ 95 #define HMSVM_VMCB_CLEAN_AVIC RT_BIT(11) 96 /** @} */ 68 97 69 98 /** … … 788 817 789 818 790 DECLINLINE(void) hmR0VmxSvmAddXcptIntercept(uint32_t u32Xcpt) 791 { 792 if (!(pVmcb->ctrl.u32InterceptException & u32Xcpt) 793 { 794 pVmcb->ctrl.u32InterceptException |= u32Xcpt; 795 pVCpu->hm.s.fContextUseFlags |= HM_CHANGED_SVM_INTERCEPT_VECTORS; 796 } 797 } 798 799 DECLINLINE(void) hmR0VmxSvmRemoveXcptIntercept(uint32_t u32Xcpt) 800 { 801 if (pVmcb->ctrl.u32InterceptException & u32Xcpt) 802 { 803 pVmcb->ctrl.u32InterceptException &= ~u32Xcpt; 804 pVCpu->hm.s.fContextUseFlags |= HM_CHANGED_SVM_INTERCEPT_VECTORS; 805 } 819 DECLINLINE(void) hmR0SvmAddXcptIntercept(uint32_t u32Xcpt) 820 { 821 if (!(pVmcb->ctrl.u32InterceptException & RT_BIT(u32Xcpt)) 822 { 823 pVmcb->ctrl.u32InterceptException |= RT_BIT(u32Xcpt); 824 pVmcb->u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_INTERCEPTS; 825 } 826 } 827 828 DECLINLINE(void) hmR0SvmRemoveXcptIntercept(uint32_t u32Xcpt) 829 { 830 #ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS 831 if (pVmcb->ctrl.u32InterceptException & RT_BIT(u32Xcpt)) 832 { 833 pVmcb->ctrl.u32InterceptException &= ~RT_BIT(u32Xcpt); 834 pVmcb->u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_INTERCEPTS; 835 } 836 #endif 806 837 } 807 838 … … 829 860 830 861 /* 831 * With Nested Paging, the guest is allowed to run with paging disabled; guest-physical to host-physical translations 832 * will remain active through the Nested CR3. AMD supports paged real-mode, See AMD spec. 15.19 "Paged Real Mode". 862 * When Nested Paging is not available use shadow page tables and intercept #PFs (latter done in SVMR0SetupVM()). 833 863 */ 834 864 if (!pVM->hm.s.fNestedPaging) 835 865 { 836 u64GuestCR0 |= X86_CR0_PG; /* When Nested Paging is not available use shadow page tables. */866 u64GuestCR0 |= X86_CR0_PG; /* When Nested Paging is not available, use shadow page tables. */ 837 867 u64GuestCR0 |= X86_CR0_WP; /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */ 838 868 } … … 865 895 */ 866 896 if (fInterceptNM) 867 hmR0 VmxSvmAddXcptIntercept(RT_BIT(X86_XCPT_NM));897 hmR0SvmAddXcptIntercept(X86_XCPT_NM); 868 898 else 869 hmR0 VmxSvmRemoveXcptIntercept(RT_BIT(X86_XCPT_NM));899 hmR0SvmRemoveXcptIntercept(X86_XCPT_NM); 870 900 871 901 if (fInterceptMF) 872 hmR0 VmxSvmAddXcptIntercept(RT_BIT(X86_XCPT_MF));902 hmR0SvmAddXcptIntercept(X86_XCPT_MF); 873 903 else 874 hmR0 VmxSvmRemoveXcptIntercept(RT_BIT(X86_XCPT_MF));904 hmR0SvmRemoveXcptIntercept(X86_XCPT_MF); 875 905 876 906 pVmcb->guest.u64CR0 = u64GuestCR0; … … 1056 1086 } 1057 1087 1088 /** 1089 * Loads the guest debug registers into the VMCB. 1090 * 1091 * @param pVCpu Pointer to the VMCPU. 1092 * @param pCtx Pointer to the guest-CPU context. 1093 * 1094 * @remarks No-long-jump zone!!! 1095 */ 1096 static void hmR0SvmLoadGuestDebugRegs(PVMCPU pVCpu, PCPUMCTX pCtx) 1097 { 1098 if (!(pVCpu->hm.s.fContextUseFlags & HM_CHANGED_GUEST_DEBUG)) 1099 return; 1100 1101 /** @todo Turn these into assertions if possible. */ 1102 pCtx->dr[6] |= X86_DR6_INIT_VAL; /* Set reserved bits to 1. */ 1103 pCtx->dr[6] &= ~RT_BIT(12); /* MBZ. */ 1104 1105 pCtx->dr[7] &= 0xffffffff; /* Upper 32 bits MBZ. */ 1106 pCtx->dr[7] &= ~(RT_BIT(11) | RT_BIT(12) | RT_BIT(14) | RT_BIT(15)); /* MBZ. */ 1107 pCtx->dr[7] |= 0x400; /* MB1. */ 1108 1109 /* Update DR6, DR7 with the guest values. */ 1110 pVmcb->guest.u64DR7 = pCtx->dr[7]; 1111 pVmcb->guest.u64DR6 = pCtx->dr[6]; 1112 pVmcb->u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_DRX; 1113 1114 bool fInterceptDB = false; 1115 bool fInterceptMovDRx = false; 1116 if (DBGFIsStepping(pVCpu)) 1117 { 1118 /* AMD-V doesn't have any monitor-trap flag equivalent. Instead, enable tracing in the guest and trap #DB. */ 1119 pVmcb->guest.u64RFlags |= X86_EFL_TF; 1120 fInterceptDB = true; 1121 } 1122 1123 if (CPUMGetHyperDR7(pVCpu) & (X86_DR7_ENABLED_MASK | X86_DR7_GD)) 1124 { 1125 if (!CPUMIsHyperDebugStateActive(pVCpu)) 1126 { 1127 rc = CPUMR0LoadHyperDebugState(pVM, pVCpu, pMixedCtx, true /* include DR6 */); 1128 AssertRC(rc); 1129 1130 /* Update DR6, DR7 with the hypervisor values. */ 1131 pVmcb->guest.u64DR7 = CPUMGetHyperDR7(pVCpu); 1132 pVmcb->guest.u64DR6 = CPUMGetHyperDR6(pVCpu); 1133 pVmcb->u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_DRX; 1134 } 1135 Assert(CPUMIsHyperDebugStateActive(pVCpu)); 1136 fInterceptMovDRx = true; 1137 } 1138 else if (pMixedCtx->dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD)) 1139 { 1140 if (!CPUMIsGuestDebugStateActive(pVCpu)) 1141 { 1142 rc = CPUMR0LoadGuestDebugState(pVM, pVCpu, pMixedCtx, true /* include DR6 */); 1143 AssertRC(rc); 1144 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed); 1145 } 1146 Assert(CPUMIsGuestDebugStateActive(pVCpu)); 1147 Assert(fInterceptMovDRx == false); 1148 } 1149 else if (!CPUMIsGuestDebugStateActive(pVCpu)) 1150 { 1151 /* For the first time we would need to intercept MOV DRx accesses even when the guest debug registers aren't loaded. */ 1152 fInterceptMovDRx = true; 1153 } 1154 1155 if (fInterceptDB) 1156 hmR0SvmAddXcptIntercept(X86_XCPT_DB); 1157 else 1158 hmR0SvmRemoveXcptIntercept(X86_XCPT_DB); 1159 1160 if (fInterceptMovDRx) 1161 { 1162 if ( pVmcb->ctrl.u16InterceptRdDRx != 0xffff 1163 || pVmcb->ctrl.u16InterceptWrDRx != 0xffff) 1164 { 1165 pVmcb->ctrl.u16InterceptRdDRx = 0xffff; 1166 pVmcb->ctrl.u16InterceptWrDRx = 0xffff; 1167 pVmcb->u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_INTERCEPTS; 1168 } 1169 } 1170 else 1171 { 1172 if ( pVmcb->ctrl.u16InterceptRdDRx 1173 || pVmcb->ctrl.u16InterceptWrDRx) 1174 { 1175 pVmcb->ctrl.u16InterceptRdDRx = 0; 1176 pVmcb->ctrl.u16InterceptWrDRx = 0; 1177 pVmcb->u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_INTERCEPTS; 1178 } 1179 } 1180 1181 pVCpu->hm.s.fContextUseFlags &= ~HM_CHANGED_GUEST_DEBUG; 1182 } 1058 1183 1059 1184 /** … … 1127 1252 pVmcb->guest.u8CPL = pCtx->ss.Attr.n.u2Dpl; 1128 1253 1254 /* hmR0SvmLoadGuestDebugRegs() must be called -after- updating guest RFLAGS as the RFLAGS may need to be changed. */ 1255 hmR0SvmLoadGuestDebugRegs(pVCpu, pCtx); 1256 1129 1257 /* Guest RAX (VMRUN uses RAX as an implicit parameter). */ 1130 1258 pVmcb->guest.u64RAX = pCtx->rax; 1259 1260 /* -XXX tsc offsetting */ 1131 1261 1132 1262 rc = hmR0SvmSetupVMRunHandler(pVCpu, pMixedCtx);
Note:
See TracChangeset
for help on using the changeset viewer.