Changeset 75320 in vbox
- Timestamp:
- Nov 8, 2018 12:16:27 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 126436
- Location:
- trunk
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/cpum.h
r74834 r75320 1962 1962 } 1963 1963 1964 1965 /** 1966 * Returns the guest-physical address of the APIC-access page when executing a 1967 * nested-guest. 1968 * 1969 * @returns The APIC-access page guest-physical address. 1970 * @param pVCpu The cross context virtual CPU structure of the calling EMT. 1971 * @param pCtx Pointer to the context. 1972 */ 1973 DECLINLINE(uint64_t) CPUMGetGuestVmxApicAccessPageAddr(PVMCPU pVCpu, PCCPUMCTX pCtx) 1974 { 1975 RT_NOREF(pVCpu); 1976 Assert(pCtx->hwvirt.enmHwvirt == CPUMHWVIRT_VMX); 1977 Assert(pCtx->hwvirt.vmx.fInVmxNonRootMode); 1978 Assert(pCtx->hwvirt.vmx.CTX_SUFF(pVmcs)); 1979 return pCtx->hwvirt.vmx.CTX_SUFF(pVmcs)->u64AddrApicAccess.u; 1980 } 1981 1964 1982 # endif /* !IN_RC */ 1965 1983 -
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r75201 r75320 447 447 do { return iemVmxVmexitTripleFault(a_pVCpu); } while (0) 448 448 449 # define IEM_VMX_VMEXIT_APIC_ACCESS_RET(a_pVCpu, a_offAccess, a_fAccess) \ 450 do { return iemVmxVmexitApicAccess((a_pVCpu), (a_offAccess), (a_fAccess)); } while (0) 451 449 452 #else 450 453 # define IEM_VMX_IS_ROOT_MODE(a_pVCpu) (false) … … 458 461 # define IEM_VMX_VMEXIT_MWAIT_RET(a_pVCpu, a_fMonitorArmed, a_cbInstr) do { return VERR_VMX_IPE_1; } while (0) 459 462 # define IEM_VMX_VMEXIT_TRIPLE_FAULT_RET(a_pVCpu) do { return VERR_VMX_IPE_1; } while (0) 463 # define IEM_VMX_VMEXIT_APIC_ACCESS_RET(a_pVCpu, a_offAccess, a_fAccess) do { return VERR_VMX_IPE_1; } while (0) 460 464 461 465 #endif … … 976 980 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX 977 981 IEM_STATIC VBOXSTRICTRC iemVmxVmexitTaskSwitch(PVMCPU pVCpu, IEMTASKSWITCH enmTaskSwitch, RTSEL SelNewTss, uint8_t cbInstr); 978 IEM_STATIC VBOXSTRICTRC iemVmxVmexitEvent(PVMCPU pVCpu, uint8_t uVector, uint32_t fFlags, uint32_t uErrCode, uint64_t uCr2, 979 uint8_t cbInstr); 982 IEM_STATIC VBOXSTRICTRC iemVmxVmexitEvent(PVMCPU pVCpu, uint8_t uVector, uint32_t fFlags, uint32_t uErrCode, uint64_t uCr2, uint8_t cbInstr); 980 983 IEM_STATIC VBOXSTRICTRC iemVmxVmexitTripleFault(PVMCPU pVCpu); 981 984 IEM_STATIC VBOXSTRICTRC iemVmxVmexitPreemptTimer(PVMCPU pVCpu); … … 984 987 IEM_STATIC VBOXSTRICTRC iemVmxVmexitInitIpi(PVMCPU pVCpu); 985 988 IEM_STATIC VBOXSTRICTRC iemVmxVmexitIntWindow(PVMCPU pVCpu); 989 IEM_STATIC VBOXSTRICTRC iemVmxVirtApicAccessMem(PVMCPU pVCpu, uint16_t offAccess, size_t cbAccess, void *pvData, uint32_t fAccess); 990 IEM_STATIC VBOXSTRICTRC iemVmxVmexitApicAccess(PVMCPU pVCpu, uint16_t offAccess, uint32_t fAccess); 986 991 #endif 987 992 988 993 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM 989 994 IEM_STATIC VBOXSTRICTRC iemSvmVmexit(PVMCPU pVCpu, uint64_t uExitCode, uint64_t uExitInfo1, uint64_t uExitInfo2); 990 IEM_STATIC VBOXSTRICTRC iemHandleSvmEventIntercept(PVMCPU pVCpu, uint8_t u8Vector, uint32_t fFlags, uint32_t uErr, 991 uint64_t uCr2); 995 IEM_STATIC VBOXSTRICTRC iemHandleSvmEventIntercept(PVMCPU pVCpu, uint8_t u8Vector, uint32_t fFlags, uint32_t uErr, uint64_t uCr2); 992 996 #endif 993 997 … … 8598 8602 return rcStrict; 8599 8603 GCPhysSecond &= ~(RTGCPHYS)PAGE_OFFSET_MASK; 8604 8605 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX 8606 /* 8607 * Check if we need to cause an APIC-access VM-exit. 8608 * 8609 * The reason we do have to check whether the access is to be virtualized here is that 8610 * we already know we're crossing a page-boundary. Any cross-page access (which is at 8611 * most 4 bytes) involves accessing offsets prior to XAPIC_OFF_ID or extends well beyond 8612 * XAPIC_OFF_END + 4 bytes of the APIC-access page and hence must cause a VM-exit. 8613 */ 8614 if ( CPUMIsGuestInVmxNonRootMode(IEM_GET_CTX(pVCpu)) 8615 && IEM_VMX_IS_PROCCTLS2_SET(pVCpu, VMX_PROC_CTLS2_VIRT_APIC_ACCESS)) 8616 { 8617 RTGCPHYS const GCPhysMemFirst = GCPhysFirst & ~(RTGCPHYS)PAGE_OFFSET_MASK; 8618 RTGCPHYS const GCPhysMemSecond = GCPhysSecond & ~(RTGCPHYS)PAGE_OFFSET_MASK; 8619 RTGCPHYS const GCPhysApicAccessBase = CPUMGetGuestVmxApicAccessPageAddr(pVCpu, IEM_GET_CTX(pVCpu)) 8620 & ~(RTGCPHYS)PAGE_OFFSET_MASK; 8621 if ( GCPhysMemFirst == GCPhysApicAccessBase 8622 || GCPhysMemSecond == GCPhysApicAccessBase) 8623 { 8624 uint16_t const offAccess = GCPhysFirst & (RTGCPHYS)PAGE_OFFSET_MASK; 8625 IEM_VMX_VMEXIT_APIC_ACCESS_RET(pVCpu, offAccess, fAccess); 8626 } 8627 } 8628 #endif 8600 8629 8601 8630 PVM pVM = pVCpu->CTX_SUFF(pVM); … … 8879 8908 iemMemUpdateWrittenCounter(pVCpu, fAccess, cbMem); 8880 8909 *ppvMem = pvMem; 8910 8911 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX 8912 /* 8913 * Check if this is an APIC-access and whether it needs to be virtualized. 8914 */ 8915 if ( CPUMIsGuestInVmxNonRootMode(IEM_GET_CTX(pVCpu)) 8916 && IEM_VMX_IS_PROCCTLS2_SET(pVCpu, VMX_PROC_CTLS2_VIRT_APIC_ACCESS)) 8917 { 8918 RTGCPHYS const GCPhysMemAccessBase = GCPhysFirst & ~(RTGCPHYS)PAGE_OFFSET_MASK; 8919 RTGCPHYS const GCPhysApicAccessBase = CPUMGetGuestVmxApicAccessPageAddr(pVCpu, IEM_GET_CTX(pVCpu)) 8920 & ~(RTGCPHYS)PAGE_OFFSET_MASK; 8921 if (GCPhysMemAccessBase == GCPhysApicAccessBase) 8922 { 8923 Assert(pvMem); 8924 uint16_t const offAccess = GCPhysFirst & (RTGCPHYS)PAGE_OFFSET_MASK; 8925 return iemVmxVirtApicAccessMem(pVCpu, offAccess, cbMem, pvMem, fAccess); 8926 } 8927 } 8928 #endif 8929 8881 8930 return VINF_SUCCESS; 8882 8931 } … … 13894 13943 /* nested hw.virt codes: */ 13895 13944 || rcStrict == VINF_VMX_VMEXIT 13945 || rcStrict == VINF_VMX_MODIFIES_BEHAVIOR 13896 13946 || rcStrict == VINF_SVM_VMEXIT 13897 13947 , ("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict))); … … 13899 13949 int32_t const rcPassUp = pVCpu->iem.s.rcPassUp; 13900 13950 #ifdef VBOX_WITH_NESTED_HWVIRT_VMX 13901 if ( rcStrict == VINF_VMX_VMEXIT 13951 if ( ( rcStrict == VINF_VMX_VMEXIT 13952 || rcStrict == VINF_VMX_MODIFIES_BEHAVIOR) 13902 13953 && rcPassUp == VINF_SUCCESS) 13903 13954 rcStrict = VINF_SUCCESS; -
trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
r75316 r75320 4000 4000 * IEM_ACCESS_TYPE_WRITE). 4001 4001 */ 4002 IEM_STATIC bool iemVmxVirtApicIsAccessIntercepted(PVMCPU pVCpu, uint16_t offAccess, uint32_t cbAccess, uint32_t fAccess)4002 IEM_STATIC bool iemVmxVirtApicIsAccessIntercepted(PVMCPU pVCpu, uint16_t offAccess, size_t cbAccess, uint32_t fAccess) 4003 4003 { 4004 4004 PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); … … 4029 4029 4030 4030 /* 4031 * Check read accesses to the APIC-access page that cause VM-exits. 4032 */ 4033 if (fAccess == IEM_ACCESS_TYPE_READ) 4034 { 4031 * Check write accesses to the APIC-access page that cause VM-exits. 4032 */ 4033 if (fAccess & IEM_ACCESS_TYPE_WRITE) 4034 { 4035 if (pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_APIC_REG_VIRT) 4036 { 4037 /* 4038 * With APIC-register virtualization, a write access to any of the 4039 * following registers are virtualized. Accessing any other register 4040 * causes a VM-exit. 4041 */ 4042 uint16_t const offAlignedAccess = offAccess & 0xfffc; 4043 switch (offAlignedAccess) 4044 { 4045 case XAPIC_OFF_ID: 4046 case XAPIC_OFF_TPR: 4047 case XAPIC_OFF_EOI: 4048 case XAPIC_OFF_LDR: 4049 case XAPIC_OFF_DFR: 4050 case XAPIC_OFF_SVR: 4051 case XAPIC_OFF_ESR: 4052 case XAPIC_OFF_ICR_LO: 4053 case XAPIC_OFF_ICR_HI: 4054 case XAPIC_OFF_LVT_TIMER: 4055 case XAPIC_OFF_LVT_THERMAL: 4056 case XAPIC_OFF_LVT_PERF: 4057 case XAPIC_OFF_LVT_LINT0: 4058 case XAPIC_OFF_LVT_LINT1: 4059 case XAPIC_OFF_LVT_ERROR: 4060 case XAPIC_OFF_TIMER_ICR: 4061 case XAPIC_OFF_TIMER_DCR: 4062 break; 4063 default: 4064 return true; 4065 } 4066 } 4067 else if (pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_INT_DELIVERY) 4068 { 4069 /* 4070 * With virtual-interrupt delivery, a write access to any of the 4071 * following registers are virtualized. Accessing any other register 4072 * causes a VM-exit. 4073 * 4074 * Note! The specification does not allow writing to offsets in-between 4075 * these registers (e.g. TPR + 1 byte) unlike read accesses. 4076 */ 4077 switch (offAccess) 4078 { 4079 case XAPIC_OFF_TPR: 4080 case XAPIC_OFF_EOI: 4081 case XAPIC_OFF_ICR_LO: 4082 break; 4083 default: 4084 return true; 4085 } 4086 } 4087 else 4088 { 4089 /* 4090 * Without APIC-register virtualization or virtual-interrupt delivery, 4091 * only TPR accesses are virtualized. 4092 */ 4093 if (offAccess == XAPIC_OFF_TPR) 4094 { /* likely */ } 4095 else 4096 return true; 4097 } 4098 } 4099 else 4100 { 4101 /* 4102 * Check read accesses to the APIC-access page that cause VM-exits. 4103 */ 4035 4104 if (pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_APIC_REG_VIRT) 4036 4105 { … … 4082 4151 } 4083 4152 } 4084 else4085 {4086 /*4087 * Check write accesses to the APIC-access page that cause VM-exits.4088 */4089 if (pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_APIC_REG_VIRT)4090 {4091 /*4092 * With APIC-register virtualization, a write access to any of the4093 * following registers are virtualized. Accessing any other register4094 * causes a VM-exit.4095 */4096 uint16_t const offAlignedAccess = offAccess & 0xfffc;4097 switch (offAlignedAccess)4098 {4099 case XAPIC_OFF_ID:4100 case XAPIC_OFF_TPR:4101 case XAPIC_OFF_EOI:4102 case XAPIC_OFF_LDR:4103 case XAPIC_OFF_DFR:4104 case XAPIC_OFF_SVR:4105 case XAPIC_OFF_ESR:4106 case XAPIC_OFF_ICR_LO:4107 case XAPIC_OFF_ICR_HI:4108 case XAPIC_OFF_LVT_TIMER:4109 case XAPIC_OFF_LVT_THERMAL:4110 case XAPIC_OFF_LVT_PERF:4111 case XAPIC_OFF_LVT_LINT0:4112 case XAPIC_OFF_LVT_LINT1:4113 case XAPIC_OFF_LVT_ERROR:4114 case XAPIC_OFF_TIMER_ICR:4115 case XAPIC_OFF_TIMER_DCR:4116 break;4117 default:4118 return true;4119 }4120 }4121 else if (pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_INT_DELIVERY)4122 {4123 /*4124 * With virtual-interrupt delivery, a write access to any of the4125 * following registers are virtualized. Accessing any other register4126 * causes a VM-exit.4127 *4128 * Note! The specification does not allow writing to offsets in-between4129 * these registers (e.g. TPR + 1 byte) unlike read accesses.4130 */4131 switch (offAccess)4132 {4133 case XAPIC_OFF_TPR:4134 case XAPIC_OFF_EOI:4135 case XAPIC_OFF_ICR_LO:4136 break;4137 default:4138 return true;4139 }4140 }4141 else4142 {4143 /*4144 * Without APIC-register virtualization or virtual-interrupt delivery,4145 * only TPR accesses are virtualized.4146 */4147 if (offAccess == XAPIC_OFF_TPR)4148 { /* likely */ }4149 else4150 return true;4151 }4152 }4153 4153 4154 4154 /* The APIC-access is virtualized, does not cause a VM-exit. */ … … 4174 4174 * @param pVCpu The cross context virtual CPU structure. 4175 4175 * @param offAccess The offset of the register being accessed. 4176 * @param fAccess The type of access (must beIEM_ACCESS_TYPE_READ or4177 * IEM_ACCESS_TYPE_WRITE ).4176 * @param fAccess The type of access (must contain IEM_ACCESS_TYPE_READ or 4177 * IEM_ACCESS_TYPE_WRITE or IEM_ACCESS_INSTRUCTION). 4178 4178 */ 4179 4179 IEM_STATIC VBOXSTRICTRC iemVmxVmexitApicAccess(PVMCPU pVCpu, uint16_t offAccess, uint32_t fAccess) 4180 4180 { 4181 Assert( fAccess == IEM_ACCESS_TYPE_READ || fAccess == IEM_ACCESS_TYPE_WRITE);4181 Assert((fAccess & IEM_ACCESS_TYPE_READ) || (fAccess & IEM_ACCESS_TYPE_WRITE) || (fAccess & IEM_ACCESS_INSTRUCTION)); 4182 4182 4183 4183 VMXAPICACCESS enmAccess; … … 4185 4185 if (fInEventDelivery) 4186 4186 enmAccess = VMXAPICACCESS_LINEAR_EVENT_DELIVERY; 4187 else if (fAccess == IEM_ACCESS_TYPE_READ) 4188 enmAccess = VMXAPICACCESS_LINEAR_READ; 4187 else if (fAccess & IEM_ACCESS_INSTRUCTION) 4188 enmAccess = VMXAPICACCESS_LINEAR_INSTR_FETCH; 4189 else if (fAccess & IEM_ACCESS_TYPE_WRITE) 4190 enmAccess = VMXAPICACCESS_LINEAR_WRITE; 4189 4191 else 4190 4192 enmAccess = VMXAPICACCESS_LINEAR_WRITE; … … 4198 4200 4199 4201 /** 4200 * Virtualizes a n APIC readaccess.4202 * Virtualizes a memory-based APIC-access. 4201 4203 * 4202 4204 * @returns VBox strict status code. 4203 4205 * @param pVCpu The cross context virtual CPU structure. 4204 * @param offAccess The offset of the register being read. 4205 * @param cbAccess The size of the APIC access. 4206 * @param pvData Where to store the read data. 4207 */ 4208 IEM_STATIC VBOXSTRICTRC iemVmxVirtApicRead(PVMCPU pVCpu, uint16_t offAccess, uint32_t cbAccess, void *pvData) 4206 * @param offAccess The offset of the register being accessed (within the 4207 * APIC-access page). 4208 * @param cbAccess The size of the access in bytes. 4209 * @param pvData Pointer to the data being read or written. 4210 * @param fAccess The type of access (must contain IEM_ACCESS_TYPE_READ or 4211 * IEM_ACCESS_TYPE_WRITE or IEM_ACCESS_INSTRUCTION). 4212 */ 4213 IEM_STATIC VBOXSTRICTRC iemVmxVirtApicAccessMem(PVMCPU pVCpu, uint16_t offAccess, size_t cbAccess, void *pvData, 4214 uint32_t fAccess) 4209 4215 { 4210 4216 PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); … … 4212 4218 Assert(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS); 4213 4219 Assert(pvData); 4214 4215 /* Check if we need to cause a VM-exit for this APIC access. */ 4216 bool const fIntercept = iemVmxVirtApicIsAccessIntercepted(pVCpu, offAccess, cbAccess, IEM_ACCESS_TYPE_READ); 4220 Assert( (fAccess & IEM_ACCESS_TYPE_READ) 4221 || (fAccess & IEM_ACCESS_TYPE_WRITE) 4222 || (fAccess & IEM_ACCESS_INSTRUCTION)); 4223 4224 bool const fIntercept = iemVmxVirtApicIsAccessIntercepted(pVCpu, offAccess, cbAccess, fAccess); 4217 4225 if (fIntercept) 4218 return iemVmxVmexitApicAccess(pVCpu, offAccess, IEM_ACCESS_TYPE_READ); 4219 4220 /* 4221 * A read access from the APIC-access page that is virtualized (rather than 4222 * causing a VM-exit) returns data from the virtual-APIC page. 4223 * 4224 * See Intel spec. 29.4.2 "Virtualizing Reads from the APIC-Access Page". 4225 */ 4226 Assert(cbAccess <= 4); 4227 Assert(offAccess < XAPIC_OFF_END + 4); 4228 static uint32_t const s_auAccessSizeMasks[] = { 0, 0xff, 0xffff, 0xffffff, 0xffffffff }; 4229 4230 uint32_t u32Data = iemVmxVirtApicReadRaw32(pVCpu, offAccess); 4231 u32Data &= s_auAccessSizeMasks[cbAccess]; 4232 *(uint32_t *)pvData = u32Data; 4233 return VINF_VMX_INTERCEPT_NOT_ACTIVE; 4234 } 4235 4236 4237 /** 4238 * Virtualizes an APIC write access. 4239 * 4240 * @returns VBox strict status code. 4241 * @param pVCpu The cross context virtual CPU structure. 4242 * @param offAccess The offset of the register being written. 4243 * @param cbAccess The size of the APIC access. 4244 * @param pvData Pointer to the data being written. 4245 */ 4246 IEM_STATIC VBOXSTRICTRC iemVmxVirtApicWrite(PVMCPU pVCpu, uint16_t offAccess, uint32_t cbAccess, void *pvData) 4247 { 4248 PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 4249 Assert(pVmcs); 4250 Assert(pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS); 4251 Assert(pvData); 4252 4253 /* Check if we need to cause a VM-exit for this APIC access. */ 4254 bool const fIntercept = iemVmxVirtApicIsAccessIntercepted(pVCpu, offAccess, cbAccess, IEM_ACCESS_TYPE_WRITE); 4255 if (fIntercept) 4256 return iemVmxVmexitApicAccess(pVCpu, offAccess, IEM_ACCESS_TYPE_WRITE); 4257 4258 /* 4259 * A write access to the APIC-access page that is virtualized (rather than 4260 * causing a VM-exit) writes data to the virtual-APIC page. 4261 */ 4262 uint32_t const u32Data = *(uint32_t *)pvData; 4263 iemVmxVirtApicWriteRaw32(pVCpu, offAccess, u32Data); 4264 4265 /* 4266 * Record the currently updated APIC offset, as we need this later for figuring 4267 * out what to do as well as the exit qualification when causing an APIC-write VM-exit. 4268 */ 4269 pVCpu->cpum.GstCtx.hwvirt.vmx.offVirtApicWrite = offAccess; 4270 4271 /* 4272 * After completion of the current operation, we need to perform TPR virtualization, 4273 * EOI virtualization or APIC-write VM-exit depending on which register was written. 4274 * 4275 * The current operation may be a REP-prefixed string instruction, execution of any 4276 * other instruction, or delivery of an event through the IDT. 4277 * 4278 * Thus things like clearing bytes 3:1 of the VTPR, clearing VEOI are not to be 4279 * performed now but later after completion of the current operation. 4280 * 4281 * See Intel spec. 29.4.3.2 "APIC-Write Emulation". 4282 */ 4283 VMCPU_FF_SET(pVCpu, VMCPU_FF_VMX_UPDATE_VAPIC); 4284 return VINF_VMX_INTERCEPT_NOT_ACTIVE; 4226 return iemVmxVmexitApicAccess(pVCpu, offAccess, fAccess); 4227 4228 if (fAccess & IEM_ACCESS_TYPE_WRITE) 4229 { 4230 /* 4231 * Record the currently updated APIC offset, as we need this later for figuring 4232 * out what to do as well as the exit qualification when causing an APIC-write VM-exit. 4233 */ 4234 pVCpu->cpum.GstCtx.hwvirt.vmx.offVirtApicWrite = offAccess; 4235 4236 /* 4237 * A write access to the APIC-access page that is virtualized (rather than 4238 * causing a VM-exit) writes data to the virtual-APIC page. 4239 */ 4240 uint32_t const u32Data = *(uint32_t *)pvData; 4241 iemVmxVirtApicWriteRaw32(pVCpu, offAccess, u32Data); 4242 4243 /* 4244 * After completion of the current operation, we need to perform TPR virtualization, 4245 * EOI virtualization or APIC-write VM-exit depending on which register was written. 4246 * 4247 * The current operation may be a REP-prefixed string instruction, execution of any 4248 * other instruction, or delivery of an event through the IDT. 4249 * 4250 * Thus things like clearing bytes 3:1 of the VTPR, clearing VEOI are not to be 4251 * performed now but later after completion of the current operation. 4252 * 4253 * See Intel spec. 29.4.3.2 "APIC-Write Emulation". 4254 */ 4255 VMCPU_FF_SET(pVCpu, VMCPU_FF_VMX_UPDATE_VAPIC); 4256 } 4257 else 4258 { 4259 /* 4260 * A read access from the APIC-access page that is virtualized (rather than 4261 * causing a VM-exit) returns data from the virtual-APIC page. 4262 * 4263 * See Intel spec. 29.4.2 "Virtualizing Reads from the APIC-Access Page". 4264 */ 4265 Assert(cbAccess <= 4); 4266 Assert(offAccess < XAPIC_OFF_END + 4); 4267 static uint32_t const s_auAccessSizeMasks[] = { 0, 0xff, 0xffff, 0xffffff, 0xffffffff }; 4268 4269 uint32_t u32Data = iemVmxVirtApicReadRaw32(pVCpu, offAccess); 4270 u32Data &= s_auAccessSizeMasks[cbAccess]; 4271 *(uint32_t *)pvData = u32Data; 4272 } 4273 4274 return VINF_VMX_MODIFIES_BEHAVIOR; 4285 4275 } 4286 4276
Note:
See TracChangeset
for help on using the changeset viewer.