- Timestamp:
- Apr 13, 2013 9:01:30 AM (12 years ago)
- Location:
- trunk
- Files:
-
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/trpm.h
r45528 r45531 73 73 VMMDECL(RTGCUINT) TRPMGetErrorCode(PVMCPU pVCpu); 74 74 VMMDECL(RTGCUINTPTR) TRPMGetFaultAddress(PVMCPU pVCpu); 75 VMMDECL(uint8_t) TRPMGetInstrLength(PVMCPU pVCpu); 75 76 VMMDECL(int) TRPMResetTrap(PVMCPU pVCpu); 76 77 VMMDECL(int) TRPMAssertTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType); 78 VMMDECL(int) TRPMAssertXcptPF(PVMCPU pVCpu, RTGCUINTPTR uCR2, RTGCUINT uErrorCode); 77 79 VMMDECL(void) TRPMSetErrorCode(PVMCPU pVCpu, RTGCUINT uErrorCode); 78 80 VMMDECL(void) TRPMSetFaultAddress(PVMCPU pVCpu, RTGCUINTPTR uCR2); 81 VMMDECL(void) TRPMSetInstrLength(PVMCPU pVCpu, uint8_t cbInstr); 79 82 VMMDECL(bool) TRPMIsSoftwareInterrupt(PVMCPU pVCpu); 80 83 VMMDECL(bool) TRPMHasTrap(PVMCPU pVCpu); 81 VMMDECL(int) TRPMQueryTrapAll(PVMCPU pVCpu, uint8_t *pu8TrapNo, PTRPMEVENT pEnmType, PRTGCUINT puErrorCode, PRTGCUINTPTR puCR2 );84 VMMDECL(int) TRPMQueryTrapAll(PVMCPU pVCpu, uint8_t *pu8TrapNo, PTRPMEVENT pEnmType, PRTGCUINT puErrorCode, PRTGCUINTPTR puCR2, uint8_t *pu8InstrLen); 82 85 VMMDECL(void) TRPMSaveTrap(PVMCPU pVCpu); 83 86 VMMDECL(void) TRPMRestoreTrap(PVMCPU pVCpu); -
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r44528 r45531 7565 7565 RTGCUINT uErrCode; 7566 7566 RTGCPTR uCr2; 7567 int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrCode, &uCr2 ); AssertRC(rc2);7567 int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrCode, &uCr2, NULL /* pu8InstLen */); AssertRC(rc2); 7568 7568 IEMInjectTrap(pVCpu, u8TrapNo, enmType, (uint16_t)uErrCode, uCr2); 7569 7569 if (!IEM_VERIFICATION_ENABLED(pIemCpu)) -
trunk/src/VBox/VMM/VMMAll/TRPMAll.cpp
r45528 r45531 51 51 * @param pEnmType Where to store the trap type 52 52 */ 53 VMMDECL(int) 53 VMMDECL(int) TRPMQueryTrap(PVMCPU pVCpu, uint8_t *pu8TrapNo, TRPMEVENT *pEnmType) 54 54 { 55 55 /* … … 78 78 * @param pVCpu Pointer to the VMCPU. 79 79 */ 80 VMMDECL(uint8_t) 80 VMMDECL(uint8_t) TRPMGetTrapNo(PVMCPU pVCpu) 81 81 { 82 82 AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n")); … … 94 94 * @param pVCpu Pointer to the VMCPU. 95 95 */ 96 VMMDECL(RTGCUINT) 96 VMMDECL(RTGCUINT) TRPMGetErrorCode(PVMCPU pVCpu) 97 97 { 98 98 AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n")); … … 100 100 switch (pVCpu->trpm.s.uActiveVector) 101 101 { 102 case 0x0a:103 case 0x0b:104 case 0x0c:105 case 0x0d:106 case 0x0e:107 case 0x11:108 case 0x08:102 case X86_XCPT_TS: 103 case X86_XCPT_NP: 104 case X86_XCPT_SS: 105 case X86_XCPT_GP: 106 case X86_XCPT_PF: 107 case X86_XCPT_AC: 108 case X86_XCPT_DF: 109 109 break; 110 110 default: … … 132 132 return pVCpu->trpm.s.uActiveCR2; 133 133 } 134 135 136 /** 137 * Gets the instruction-length for the current trap (only relevant for software 138 * interrupts and software exceptions #BP and #OF). 139 * 140 * The caller is responsible for making sure there is an active trap 0x0e when 141 * making this request. 142 * 143 * @returns Fault address associated with the trap. 144 * @param pVCpu Pointer to the VMCPU. 145 */ 146 VMMDECL(uint8_t) TRPMGetInstrLength(PVMCPU pVCpu) 147 { 148 AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n")); 149 return pVCpu->trpm.s.cbInstr; 150 } 151 134 152 135 153 … … 173 191 * @param enmType Trap type. 174 192 */ 175 VMMDECL(int) 193 VMMDECL(int) TRPMAssertTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType) 176 194 { 177 195 Log2(("TRPMAssertTrap: u8TrapNo=%02x type=%d\n", u8TrapNo, enmType)); … … 190 208 pVCpu->trpm.s.uActiveErrorCode = ~(RTGCUINT)0; 191 209 pVCpu->trpm.s.uActiveCR2 = 0xdeadface; 210 pVCpu->trpm.s.cbInstr = UINT8_MAX; 211 return VINF_SUCCESS; 212 } 213 214 215 /** 216 * Assert a page-fault exception. 217 * 218 * The caller is responsible for making sure there is no active trap 219 * when making this request. 220 * 221 * @returns VBox status code. 222 * @param pVCpu Pointer to the VMCPU. 223 * @param uCR2 The new fault address. 224 * @param uErrorCode The error code for the page-fault. 225 */ 226 VMMDECL(int) TRPMAssertXcptPF(PVMCPU pVCpu, RTGCUINTPTR uCR2, RTGCUINT uErrorCode) 227 { 228 Log2(("TRPMAssertXcptPF: uCR2=%RGv uErrorCode=%RGv\n", uCR2, uErrorCode)); /** @todo RTGCUINT to be fixed. */ 229 230 /* 231 * Cannot assert a trap when one is already active. 232 */ 233 if (pVCpu->trpm.s.uActiveVector != ~0U) 234 { 235 AssertMsgFailed(("CPU%d: Active trap %#x\n", pVCpu->idCpu, pVCpu->trpm.s.uActiveVector)); 236 return VERR_TRPM_ACTIVE_TRAP; 237 } 238 239 pVCpu->trpm.s.uActiveVector = X86_XCPT_PF; 240 pVCpu->trpm.s.enmActiveType = TRPM_TRAP; 241 pVCpu->trpm.s.uActiveErrorCode = uErrorCode; 242 pVCpu->trpm.s.uActiveCR2 = uCR2; 243 pVCpu->trpm.s.cbInstr = UINT8_MAX; 192 244 return VINF_SUCCESS; 193 245 } … … 204 256 * @param uErrorCode The new error code. 205 257 */ 206 VMMDECL(void) 258 VMMDECL(void) TRPMSetErrorCode(PVMCPU pVCpu, RTGCUINT uErrorCode) 207 259 { 208 260 Log2(("TRPMSetErrorCode: uErrorCode=%RGv\n", uErrorCode)); /** @todo RTGCUINT mess! */ … … 227 279 228 280 /** 229 * Sets the error code of the current trap.230 * (This function is for use intrap handlers and such.)281 * Sets the fault address of the current #PF trap. (This function is for use in 282 * trap handlers and such.) 231 283 * 232 284 * The caller is responsible for making sure there is an active trap 0e … … 236 288 * @param uCR2 The new fault address (cr2 register). 237 289 */ 238 VMMDECL(void) 290 VMMDECL(void) TRPMSetFaultAddress(PVMCPU pVCpu, RTGCUINTPTR uCR2) 239 291 { 240 292 Log2(("TRPMSetFaultAddress: uCR2=%RGv\n", uCR2)); 241 293 AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n")); 242 AssertMsg(pVCpu->trpm.s.uActiveVector == 0xe, ("Not trap 0e!\n"));294 AssertMsg(pVCpu->trpm.s.uActiveVector == X86_XCPT_PF, ("Not trap 0e!\n")); 243 295 pVCpu->trpm.s.uActiveCR2 = uCR2; 296 } 297 298 299 /** 300 * Sets the instruction-length of the current trap (relevant for software 301 * interrupts and software exceptions like #BP, #OF). 302 * 303 * The caller is responsible for making sure there is an active trap 0e 304 * when making this request. 305 * 306 * @param pVCpu Pointer to the VMCPU. 307 * @param cbInstr The instruction length. 308 */ 309 VMMDECL(void) TRPMSetInstrLength(PVMCPU pVCpu, uint8_t cbInstr) 310 { 311 Log2(("TRPMSetInstrLength: cbInstr=%u\n", cbInstr)); 312 AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n")); 313 AssertMsg( pVCpu->trpm.s.enmActiveType == TRPM_SOFTWARE_INT 314 || ( pVCpu->trpm.s.enmActiveType == TRPM_TRAP 315 && ( pVCpu->trpm.s.uActiveVector == X86_XCPT_BP 316 || pVCpu->trpm.s.uActiveVector == X86_XCPT_OF)), 317 ("Invalid trap type %#x\n", pVCpu->trpm.s.enmActiveType)); 318 pVCpu->trpm.s.cbInstr = cbInstr; 244 319 } 245 320 … … 269 344 * @param pVCpu Pointer to the VMCPU. 270 345 */ 271 VMMDECL(bool) 346 VMMDECL(bool) TRPMHasTrap(PVMCPU pVCpu) 272 347 { 273 348 return pVCpu->trpm.s.uActiveVector != ~0U; … … 286 361 * ~0U is stored if the trap has no error code. 287 362 * @param puCR2 Where to store the CR2 associated with a trap 0E. 288 */ 289 VMMDECL(int) TRPMQueryTrapAll(PVMCPU pVCpu, uint8_t *pu8TrapNo, TRPMEVENT *pEnmType, PRTGCUINT puErrorCode, PRTGCUINTPTR puCR2) 363 * @param pu8InstrLen Where to store the instruction-length 364 * associated with some traps. 365 */ 366 VMMDECL(int) TRPMQueryTrapAll(PVMCPU pVCpu, uint8_t *pu8TrapNo, TRPMEVENT *pEnmType, PRTGCUINT puErrorCode, PRTGCUINTPTR puCR2, 367 uint8_t *pu8InstrLen) 290 368 { 291 369 /* … … 303 381 if (puCR2) 304 382 *puCR2 = pVCpu->trpm.s.uActiveCR2; 305 383 if (pu8InstrLen) 384 *pu8InstrLen = pVCpu->trpm.s.cbInstr; 306 385 return VINF_SUCCESS; 307 386 } … … 323 402 pVCpu->trpm.s.uSavedErrorCode = pVCpu->trpm.s.uActiveErrorCode; 324 403 pVCpu->trpm.s.uSavedCR2 = pVCpu->trpm.s.uActiveCR2; 404 pVCpu->trpm.s.cbSavedInstr = pVCpu->trpm.s.cbInstr; 325 405 } 326 406 … … 339 419 pVCpu->trpm.s.uActiveErrorCode = pVCpu->trpm.s.uSavedErrorCode; 340 420 pVCpu->trpm.s.uActiveCR2 = pVCpu->trpm.s.uSavedCR2; 421 pVCpu->trpm.s.cbInstr = pVCpu->trpm.s.cbSavedInstr; 341 422 } 342 423 … … 788 869 pVCpu->trpm.s.uActiveErrorCode = 0xdeadbeef; 789 870 pVCpu->trpm.s.uActiveCR2 = 0xdeadface; 871 pVCpu->trpm.s.cbInstr = UINT8_MAX; 790 872 return VINF_EM_RAW_GUEST_TRAP; 791 873 } … … 815 897 pVCpu->trpm.s.uActiveErrorCode = uErr; 816 898 pVCpu->trpm.s.uActiveCR2 = 0xdeadface; 899 pVCpu->trpm.s.cbInstr = UINT8_MAX; 817 900 return VINF_EM_RAW_GUEST_TRAP; 818 901 } … … 843 926 pVCpu->trpm.s.uActiveErrorCode = uErr; 844 927 pVCpu->trpm.s.uActiveCR2 = uCR2; 928 pVCpu->trpm.s.cbInstr = UINT8_MAX; 845 929 return VINF_EM_RAW_GUEST_TRAP; 846 930 } -
trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
r45519 r45531 5 5 6 6 /* 7 * Copyright (C) 2012 Oracle Corporation7 * Copyright (C) 2012-2013 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 112 112 #define VMX_TRANSIENT_EXIT_INTERRUPTION_ERROR_CODE RT_BIT(5) 113 113 114 /* 114 /** 115 115 * Exception bitmap mask for real-mode guests (real-on-v86). We need to intercept all exceptions manually (except #PF). 116 116 * #NM is also handled spearetely, see hmR0VmxLoadGuestControlRegs(). #PF need not be intercepted even in real-mode if … … 125 125 | RT_BIT(X86_XCPT_XF)) 126 126 127 /* Maximum VM-instruction error number. */127 /** Maximum VM-instruction error number. */ 128 128 #define VMX_INSTR_ERROR_MAX 28 129 129 … … 206 206 static void hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMX_FLUSH_VPID enmFlush, RTGCPTR GCPtr); 207 207 static int hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint64_t u64IntrInfo, 208 uint32_t cbInstr, uint32_t u32ErrCode );208 uint32_t cbInstr, uint32_t u32ErrCode, uint32_t *puIntrState); 209 209 #if HC_ARCH_BITS == 32 && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL) 210 210 static int hmR0VmxInitVmcsReadCache(PVM pVM, PVMCPU pVCpu); … … 269 269 * Global Variables * 270 270 *******************************************************************************/ 271 /** @todo Move this to hm_vmx.h. */272 271 /** 273 272 * VM-exit handler. … … 282 281 typedef DECLCALLBACK(int) FNVMEXITHANDLER(PVMCPU pVCpu, PCPUMCTX pMixedCtx, PVMXTRANSIENT pVmxTransient); 283 282 /** Pointer to VM-exit handler. */ 284 typedef FNVMEXITHANDLER *PFNVMEXITHANDLER; 285 286 static const PFNVMEXITHANDLER s_apfnVMExitHandlers[VMX_EXIT_MAX + 1] = 283 typedef FNVMEXITHANDLER *const PFNVMEXITHANDLER; 284 285 /** 286 * VMX_EXIT dispatch table. 287 */ 288 static const PFNVMEXITHANDLER g_apfnVMExitHandlers[VMX_EXIT_MAX + 1] = 287 289 { 288 290 /* 00 VMX_EXIT_XCPT_NMI */ hmR0VmxExitXcptNmi, … … 348 350 }; 349 351 350 static const char* const s_apszVmxInstrErrors[VMX_INSTR_ERROR_MAX + 1] = 352 #ifdef VBOX_STRICT 353 static const char* const g_apszVmxInstrErrors[VMX_INSTR_ERROR_MAX + 1] = 351 354 { 352 355 /* 0 */ "(Not Used)", … … 380 383 /* 28 */ "Invalid operand to INVEPT/INVVPID." 381 384 }; 382 385 #endif 383 386 384 387 /** … … 845 848 { 846 849 /* Setup the main VM exit handlers. */ 847 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS( s_apfnVMExitHandlers));848 #ifdef DEBUG849 for (unsigned i = 0; i < RT_ELEMENTS( s_apfnVMExitHandlers); i++)850 Assert( s_apfnVMExitHandlers[i]);850 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers)); 851 #ifdef VBOX_STRICT 852 for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++) 853 Assert(g_apfnVMExitHandlers[i]); 851 854 #endif 852 855 return VINF_SUCCESS; … … 2475 2478 2476 2479 /** 2477 * Loads the guest's interruptibility-state ("interrupt shadow" as AMD calls it) 2478 * into the guest-state area in the VMCS. 2479 * 2480 * @param pVM Pointer to the VM. 2480 * Gets the guest's interruptibility-state ("interrupt shadow" as AMD calls it). 2481 * 2482 * @returns 2481 2483 * @param pVCpu Pointer to the VMCPU. 2482 2484 * @param pMixedCtx Pointer to the guest-CPU context. The data may be … … 2485 2487 * 2486 2488 * @remarks No-long-jump zone!!! 2487 */ 2488 DECLINLINE(void) hmR0VmxLoadGuestIntrState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pMixedCtx) 2489 * @remarks Has side-effects with VMCPU_FF_INHIBIT_INTERRUPTS force-flag. 2490 */ 2491 DECLINLINE(uint32_t) hmR0VmxGetGuestIntrState(PVMCPU pVCpu, PCPUMCTX pMixedCtx) 2489 2492 { 2490 2493 /* … … 2496 2499 { 2497 2500 /* If inhibition is active, RIP & RFLAGS should've been accessed (i.e. read previously from the VMCS or from ring-3). */ 2498 AssertMsg((pVCpu->hm.s.vmx.fUpdatedGuestState & (VMX_UPDATED_GUEST_RIP | VMX_UPDATED_GUEST_RFLAGS)) ,2499 ("%#x\n", pVCpu->hm.s.vmx.fUpdatedGuestState));2501 AssertMsg((pVCpu->hm.s.vmx.fUpdatedGuestState & (VMX_UPDATED_GUEST_RIP | VMX_UPDATED_GUEST_RFLAGS)) 2502 == (VMX_UPDATED_GUEST_RIP | VMX_UPDATED_GUEST_RFLAGS), ("%#x\n", pVCpu->hm.s.vmx.fUpdatedGuestState)); 2500 2503 if (pMixedCtx->rip != EMGetInhibitInterruptsPC(pVCpu)) 2501 2504 { … … 2503 2506 * We can clear the inhibit force flag as even if we go back to the recompiler without executing guest code in 2504 2507 * VT-x the flag's condition to be cleared is met and thus the cleared state is correct. 2505 * hmR0VmxInjectPendingInterrupt() relies on us clearing this flag here.2506 2508 */ 2507 2509 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS); … … 2512 2514 uIntrState = VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_MOVSS; 2513 2515 } 2514 2515 Assert(!(uIntrState & 0xfffffff0)); /* Bits 31:4 MBZ. */ 2516 return uIntrState; 2517 } 2518 2519 2520 /** 2521 * Loads the guest's interruptibility-state into the guest-state area in the 2522 * VMCS. 2523 * 2524 * @returns VBox status code. 2525 * @param pVCpu Pointer to the VMCPU. 2526 * @param uIntrState The interruptibility-state to set. 2527 */ 2528 DECLINLINE(int) hmR0VmxLoadGuestIntrState(PVMCPU pVCpu, uint32_t uIntrState) 2529 { 2530 AssertMsg(!(uIntrState & 0xfffffff0), ("%#x\n", uIntrState)); /* Bits 31:4 MBZ. */ 2516 2531 Assert((uIntrState & 0x3) != 0x3); /* Block-by-STI and MOV SS cannot be simultaneously set. */ 2517 2532 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INTERRUPTIBILITY_STATE, uIntrState); 2518 AssertRC(rc); 2533 AssertRCReturn(rc, rc); 2534 return rc; 2519 2535 } 2520 2536 … … 2996 3012 return VINF_SUCCESS; 2997 3013 2998 #ifdef DEBUG3014 #ifdef VBOX_STRICT 2999 3015 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */ 3000 3016 if (pVCpu->hm.s.vmx.u32EntryCtls & VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_DEBUG) … … 3086 3102 3087 3103 3088 #ifdef DEBUG3089 /** 3090 * Debugfunction to validate segment registers.3104 #ifdef VBOX_STRICT 3105 /** 3106 * Strict function to validate segment registers. 3091 3107 */ 3092 3108 static void hmR0VmxValidateSegmentRegs(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) … … 3247 3263 } 3248 3264 } 3249 #endif /* DEBUG*/3265 #endif /* VBOX_STRICT */ 3250 3266 3251 3267 … … 3314 3330 * 3315 3331 * @remarks No-long-jump zone!!! 3316 * @remarks Requires RFLAGS (for debug assertions).3317 3332 */ 3318 3333 DECLINLINE(int) hmR0VmxLoadGuestSegmentRegs(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx) … … 3370 3385 AssertRCReturn(rc, rc); 3371 3386 3372 #ifdef DEBUG3387 #ifdef VBOX_STRICT 3373 3388 hmR0VmxValidateSegmentRegs(pVM, pVCpu, pCtx); 3374 3389 #endif … … 3785 3800 Log(("InstrError %#x\n", pVCpu->hm.s.vmx.lasterror.u32InstrError)); 3786 3801 if (pVCpu->hm.s.vmx.lasterror.u32InstrError <= VMX_INSTR_ERROR_MAX) 3787 Log(("InstrError Desc. \"%s\"\n", s_apszVmxInstrErrors[pVCpu->hm.s.vmx.lasterror.u32InstrError]));3802 Log(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.lasterror.u32InstrError])); 3788 3803 else 3789 3804 Log(("InstrError Desc. Range exceeded %u\n", VMX_INSTR_ERROR_MAX)); … … 4166 4181 #endif 4167 4182 4168 #ifdef DEBUG4169 pCache->TestIn.HCPhysCpuPage = 0;4170 pCache->TestIn.HCPhysVmcs = 0;4171 pCache->TestIn.pCache = 0;4172 pCache->TestOut.HCPhysVmcs = 0;4173 pCache->TestOut.pCache = 0;4174 pCache->TestOut.pCtx = 0;4175 pCache->TestOut.eflags = 0;4183 #ifdef VBOX_STRICT 4184 pCache->TestIn.HCPhysCpuPage = 0; 4185 pCache->TestIn.HCPhysVmcs = 0; 4186 pCache->TestIn.pCache = 0; 4187 pCache->TestOut.HCPhysVmcs = 0; 4188 pCache->TestOut.pCache = 0; 4189 pCache->TestOut.pCtx = 0; 4190 pCache->TestOut.eflags = 0; 4176 4191 #endif 4177 4192 … … 4195 4210 #endif 4196 4211 4197 #ifdef DEBUG4198 AssertMsg(pCache->TestIn.HCPhysCpuPage == HCPhysCpuPage, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysCpuPage, HCPhysCpuPage));4199 AssertMsg(pCache->TestIn.HCPhysVmcs == pVCpu->hm.s.vmx.HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,4200 pVCpu->hm.s.vmx.HCPhysVmcs));4201 AssertMsg(pCache->TestIn.HCPhysVmcs == pCache->TestOut.HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,4202 pCache->TestOut.HCPhysVmcs));4203 AssertMsg(pCache->TestIn.pCache == pCache->TestOut.pCache, ("%RGv vs %RGv\n", pCache->TestIn.pCache,4204 pCache->TestOut.pCache));4205 AssertMsg(pCache->TestIn.pCache == VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VMCSCache),4212 #ifdef VBOX_STRICT 4213 AssertMsg(pCache->TestIn.HCPhysCpuPage == HCPhysCpuPage, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysCpuPage, HCPhysCpuPage)); 4214 AssertMsg(pCache->TestIn.HCPhysVmcs == pVCpu->hm.s.vmx.HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs, 4215 pVCpu->hm.s.vmx.HCPhysVmcs)); 4216 AssertMsg(pCache->TestIn.HCPhysVmcs == pCache->TestOut.HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs, 4217 pCache->TestOut.HCPhysVmcs)); 4218 AssertMsg(pCache->TestIn.pCache == pCache->TestOut.pCache, ("%RGv vs %RGv\n", pCache->TestIn.pCache, 4219 pCache->TestOut.pCache)); 4220 AssertMsg(pCache->TestIn.pCache == VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VMCSCache), 4206 4221 ("%RGv vs %RGv\n", pCache->TestIn.pCache, VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VMCSCache))); 4207 AssertMsg(pCache->TestIn.pCtx == pCache->TestOut.pCtx, ("%RGv vs %RGv\n", pCache->TestIn.pCtx,4222 AssertMsg(pCache->TestIn.pCtx == pCache->TestOut.pCtx, ("%RGv vs %RGv\n", pCache->TestIn.pCtx, 4208 4223 pCache->TestOut.pCtx)); 4209 4224 Assert(!(pCache->TestOut.eflags & X86_EFL_IF)); … … 4639 4654 * Sets an event as a pending event to be injected into the guest. 4640 4655 * 4641 * @param pVCpu Pointer to the VMCPU. 4642 * @param u32IntrInfo The VM-entry interruption-information field. 4643 * @param cbInstr The VM-entry instruction length in bytes (for software 4644 * interrupts, exceptions and privileged software 4645 * exceptions). 4646 * @param u32ErrCode The VM-entry exception error code. 4647 */ 4648 DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPU pVCpu, uint32_t u32IntrInfo, uint32_t cbInstr, uint32_t u32ErrCode) 4656 * @param pVCpu Pointer to the VMCPU. 4657 * @param u32IntrInfo The VM-entry interruption-information field. 4658 * @param cbInstr The VM-entry instruction length in bytes (for software 4659 * interrupts, exceptions and privileged software 4660 * exceptions). 4661 * @param u32ErrCode The VM-entry exception error code. 4662 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a 4663 * page-fault. 4664 */ 4665 DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPU pVCpu, uint32_t u32IntrInfo, uint32_t cbInstr, uint32_t u32ErrCode, 4666 RTGCUINTPTR GCPtrFaultAddress) 4649 4667 { 4650 4668 Assert(!pVCpu->hm.s.Event.fPending); 4651 pVCpu->hm.s.Event.fPending = true; 4652 pVCpu->hm.s.Event.u64IntrInfo = u32IntrInfo; 4653 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode; 4654 pVCpu->hm.s.Event.cbInstr = cbInstr; 4669 pVCpu->hm.s.Event.fPending = true; 4670 pVCpu->hm.s.Event.u64IntrInfo = u32IntrInfo; 4671 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode; 4672 pVCpu->hm.s.Event.cbInstr = cbInstr; 4673 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress; 4655 4674 } 4656 4675 … … 4750 4769 } 4751 4770 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INTR_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo), 4752 0 /* cbInstr */, u32ErrCode );4771 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */); 4753 4772 rc = VINF_SUCCESS; 4754 4773 Log(("Pending event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntrInfo, pVCpu->hm.s.Event.u32ErrCode)); … … 4762 4781 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 4763 4782 u32IntrInfo |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID; 4764 hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */ );4783 hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */); 4765 4784 rc = VINF_VMX_DOUBLE_FAULT; 4766 4785 Log(("Pending #DF %#RX64 uIdt=%#x uExit=%#x\n", pVCpu->hm.s.Event.u64IntrInfo, uIdtVector, uExitVector)); … … 5539 5558 5540 5559 /** 5560 * Converts any TRPM trap into a pending VMX event. 5561 * 5562 * @param pVCpu Pointer to the VMCPU. 5563 */ 5564 static void hmR0VmxUpdatePendingEvent(PVMCPU pVCpu, PCPUMCTX pMixedCtx) 5565 { 5566 if (!TRPMHasTrap(pVCpu)) 5567 return; 5568 5569 uint8_t uVector; 5570 TRPMEVENT enmTrpmEvent; 5571 RTGCUINT uErrCode; 5572 RTGCUINTPTR GCPtrFaultAddress; 5573 uint8_t cbInstr; 5574 5575 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr); 5576 AssertRC(rc); 5577 5578 /* Refer Intel spec. 24.8.3 "VM-entry Controls for Event Injection" for the format of u32IntrInfo. */ 5579 uint32_t u32IntrInfo = uVector | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT); 5580 uint32_t u32ErrCode = uErrCode; 5581 if (enmTrpmEvent == TRPM_TRAP) 5582 { 5583 switch (uVector) 5584 { 5585 case X86_XCPT_BP: 5586 case X86_XCPT_OF: 5587 { 5588 /* These exceptions must be delivered as software exceptions. They have no error codes associated with them. */ 5589 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5590 break; 5591 } 5592 5593 case X86_XCPT_DF: 5594 case X86_XCPT_TS: 5595 case X86_XCPT_NP: 5596 case X86_XCPT_SS: 5597 case X86_XCPT_GP: 5598 case X86_XCPT_PF: 5599 case X86_XCPT_AC: 5600 /* These exceptions must be delivered as hardware exceptions. They have error codes associated with 5601 them which VT-x/VMM pushes to the guest stack. */ 5602 u32IntrInfo |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID; 5603 /* no break! */ 5604 default: 5605 { 5606 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5607 if (uVector == X86_XCPT_PF) 5608 pMixedCtx->cr2 = TRPMGetFaultAddress(pVCpu); 5609 break; 5610 } 5611 } 5612 } 5613 else if (enmTrpmEvent == TRPM_HARDWARE_INT) 5614 { 5615 if (uVector != X86_XCPT_NMI) 5616 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5617 else 5618 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5619 } 5620 else if (enmTrpmEvent == TRPM_SOFTWARE_INT) 5621 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5622 else 5623 AssertMsgFailed(("Invalid TRPM event type %d\n", enmTrpmEvent)); 5624 5625 rc = TRPMResetTrap(pVCpu); 5626 Log(("Converted TRPM trap: u32IntrInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u u32ErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n", 5627 u32IntrInfo, enmTrpmEvent, u32ErrCode, GCPtrFaultAddress)); 5628 hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, cbInstr, u32ErrCode, GCPtrFaultAddress); 5629 } 5630 5631 5632 /** 5541 5633 * Converts any pending VMX event into a TRPM trap. Typically used when leaving 5542 5634 * VT-x to execute any instruction. 5543 5635 * 5544 * @param pvCpu 5636 * @param pvCpu Pointer to the VMCPU. 5545 5637 */ 5546 5638 static void hmR0VmxUpdateTRPMTrap(PVMCPU pVCpu) … … 5554 5646 5555 5647 /* If a trap was already pending, we did something wrong! */ 5556 Assert(TRPMQueryTrap(pVCpu, NULL, NULL) == VERR_TRPM_NO_ACTIVE_TRAP); 5557 5558 /* A page-fault exception during a page-fault would become a double-fault. */ 5559 AssertMsg(uVectorType != VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT || uVector != X86_XCPT_PF, 5560 ("%#RX64 uVectorType=%#x uVector=%#x\n", pVCpu->hm.s.Event.u64IntrInfo, uVectorType, uVector)); 5648 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP); 5561 5649 5562 5650 TRPMEVENT enmTrapType; … … 5580 5668 break; 5581 5669 } 5670 5582 5671 Log(("Converting pending HM event to TRPM trap uVector=%#x enmTrapType=%d\n", uVector, enmTrapType)); 5672 5583 5673 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType); 5584 5674 AssertRC(rc); 5585 5675 if (fErrorCodeValid) 5586 5676 TRPMSetErrorCode(pVCpu, uErrorCode); 5587 AssertRC(rc); 5677 5678 /* A page-fault exception during a page-fault would become a double-fault. */ 5679 if ( uVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT 5680 && uVector == X86_XCPT_PF) 5681 { 5682 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress); 5683 } 5684 else if ( uVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT 5685 || uVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT) 5686 { 5687 AssertMsg( uVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT 5688 || (uVector == X86_XCPT_BP || uVector == X86_XCPT_OF), 5689 ("Invalid vector: uVector=%#x uVectorType=%#x\n", uVector, uVectorType)); 5690 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr); 5691 } 5588 5692 pVCpu->hm.s.Event.fPending = false; 5589 5693 } … … 5730 5834 5731 5835 /** 5732 * Injects any pending TRPM trap into the VM by updating the VMCS. 5733 * 5734 * @returns VBox status code (informational status code included). 5735 * @param pVM Pointer to the VM. 5836 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to 5837 * cause a VM-exit as soon as the guest is in a state to receive interrupts. 5838 * 5839 * @returns VBox status code. 5840 * @param pVCpu Pointer to the VMCPU. 5841 */ 5842 DECLINLINE(void) hmR0VmxSetIntWindowExitVmcs(PVMCPU pVCpu) 5843 { 5844 if (RT_LIKELY(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INT_WINDOW_EXIT)) 5845 { 5846 /* Enable interrupt-window exiting if it's not in effect already. */ 5847 if (!(pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INT_WINDOW_EXIT)) 5848 { 5849 pVCpu->hm.s.vmx.u32ProcCtls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INT_WINDOW_EXIT; 5850 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC_CONTROLS, pVCpu->hm.s.vmx.u32ProcCtls); 5851 AssertRC(rc); 5852 } 5853 } /* else we will deliver interrupts whenever the guest exits next and is in a state to receive events. */ 5854 } 5855 5856 5857 /** 5858 * Checks if there are any pending guest interrupts to be delivered and injects 5859 * them into the VM by updating the VMCS. 5860 * 5861 * @returns VBox status code (informational status codes included). 5736 5862 * @param pVCpu Pointer to the VMCPU. 5737 5863 * @param pMixedCtx Pointer to the guest-CPU context. The data may be … … 5739 5865 * before using them. 5740 5866 */ 5741 static int hmR0VmxInjectTRPMTrap(PVM pVM, PVMCPU pVCpu, PCPUMCTX pMixedCtx) 5742 { 5743 if (!TRPMHasTrap(pVCpu)) 5744 return VINF_SUCCESS; 5745 5746 uint8_t u8Vector = 0; 5747 TRPMEVENT enmTrpmEvent = TRPM_SOFTWARE_INT; 5748 RTGCUINT uErrCode = 0; 5749 5750 int rc = TRPMQueryTrapAll(pVCpu, &u8Vector, &enmTrpmEvent, &uErrCode, NULL /* puCr2 */); 5751 rc |= TRPMResetTrap(pVCpu); 5752 AssertRCReturn(rc, rc); 5753 5754 /* Refer Intel spec. 24.8.3 "VM-entry Controls for Event Injection" for the format of u32IntrInfo. */ 5755 uint32_t u32IntrInfo = u8Vector | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT); 5756 if (enmTrpmEvent == TRPM_TRAP) 5757 { 5758 switch (u8Vector) 5759 { 5760 case X86_XCPT_BP: 5761 case X86_XCPT_OF: 5867 static int hmR0VmxInjectEvent(PVMCPU pVCpu, PCPUMCTX pMixedCtx) 5868 { 5869 /* Get the current interruptibility-state of the guest and then figure out what can be injected. */ 5870 uint32_t uIntrState = hmR0VmxGetGuestIntrState(pVCpu, pMixedCtx); 5871 const bool fBlockMovSS = (uIntrState & VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_MOVSS); 5872 const bool fBlockSti = (uIntrState & VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_STI); 5873 5874 int rc = VINF_SUCCESS; 5875 if (pVCpu->hm.s.Event.fPending) /* First, inject any pending HM events. */ 5876 { 5877 uint32_t uIntrType = VMX_EXIT_INTERRUPTION_INFO_TYPE((uint32_t)pVCpu->hm.s.Event.u64IntrInfo); 5878 bool fInject = true; 5879 if (uIntrType == VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT) 5880 { 5881 rc = hmR0VmxSaveGuestRflags(pVCpu, pMixedCtx); 5882 AssertRCReturn(rc, rc); 5883 const bool fBlockInt = !(pMixedCtx->eflags.u32 & X86_EFL_IF); 5884 if ( fBlockInt 5885 || fBlockSti 5886 || fBlockMovSS) 5762 5887 { 5763 /* These exceptions must be delivered as software exceptions. They have no error codes associated with them. */ 5764 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5765 break; 5888 fInject = false; 5766 5889 } 5767 5768 case X86_XCPT_DF: 5769 case X86_XCPT_TS: 5770 case X86_XCPT_NP: 5771 case X86_XCPT_SS: 5772 case X86_XCPT_GP: 5773 case X86_XCPT_PF: 5774 case X86_XCPT_AC: 5775 /* These exceptions must be delivered as hardware exceptions. They have error codes associated with 5776 them which VT-x/VMM pushes to the guest stack. */ 5777 u32IntrInfo |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID; 5778 /* no break! */ 5779 default: 5890 } 5891 else if ( uIntrType == VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI 5892 && ( fBlockMovSS 5893 || fBlockSti)) 5894 { 5895 /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */ 5896 fInject = false; 5897 } 5898 5899 if (fInject) 5900 { 5901 Log(("Injecting pending event\n")); 5902 rc = hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, pVCpu->hm.s.Event.u64IntrInfo, pVCpu->hm.s.Event.cbInstr, 5903 pVCpu->hm.s.Event.u32ErrCode, &uIntrState); 5904 AssertRCReturn(rc, rc); 5905 pVCpu->hm.s.Event.fPending = false; 5906 } 5907 } /** @todo SMI. SMIs take priority over NMIs. */ 5908 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI)) /* NMI. NMIs take priority over regular interrupts . */ 5909 { 5910 /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */ 5911 if (!fBlockMovSS && !fBlockSti) 5912 { 5913 Log(("Injecting NMI\n")); 5914 RTGCUINTPTR uIntrInfo; 5915 uIntrInfo = X86_XCPT_NMI; 5916 uIntrInfo |= (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT); 5917 uIntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5918 rc = hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, uIntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, &uIntrState); 5919 AssertRCReturn(rc, rc); 5920 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI); 5921 } 5922 else 5923 hmR0VmxSetIntWindowExitVmcs(pVCpu); 5924 } 5925 else if (VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))) 5926 { 5927 /* Check if there are guest external interrupts (PIC/APIC) pending and inject them if the guest can receive them. */ 5928 rc = hmR0VmxSaveGuestRflags(pVCpu, pMixedCtx); 5929 AssertRCReturn(rc, rc); 5930 const bool fBlockInt = !(pMixedCtx->eflags.u32 & X86_EFL_IF); 5931 if ( !fBlockInt 5932 && !fBlockSti 5933 && !fBlockMovSS) 5934 { 5935 uint8_t u8Interrupt = 0; 5936 rc = PDMGetInterrupt(pVCpu, &u8Interrupt); 5937 if (RT_SUCCESS(rc)) 5780 5938 { 5781 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5782 break; 5939 Log(("Injecting interrupt u8Interrupt=%#x\n", u8Interrupt)); 5940 uint32_t u32IntrInfo = u8Interrupt | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT); 5941 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5942 rc = hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, &uIntrState); 5783 5943 } 5784 } 5785 } 5786 else if (enmTrpmEvent == TRPM_HARDWARE_INT) 5787 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5788 else if (enmTrpmEvent == TRPM_SOFTWARE_INT) 5789 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5790 else 5791 AssertMsgFailed(("Invalid TRPM event type %d\n", enmTrpmEvent)); 5792 5793 STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject); 5794 return hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */, uErrCode); 5795 } 5796 5797 5798 /** 5799 * Checks if there are any pending guest interrupts to be delivered and injects 5800 * them into the VM by updating the VMCS. 5801 * 5802 * @returns VBox status code (informational status codes included). 5803 * @param pVM Pointer to the VM. 5944 else 5945 { 5946 /** @todo Does this actually happen? If not turn it into an assertion. */ 5947 Assert(!VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))); 5948 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq); 5949 rc = VINF_SUCCESS; 5950 } 5951 } 5952 else 5953 hmR0VmxSetIntWindowExitVmcs(pVCpu); 5954 } 5955 5956 /* 5957 * There's no need to clear the entry-interruption information field here if we're not injecting anything. 5958 * VT-x clears the valid bit on every VM-exit. See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection". 5959 */ 5960 hmR0VmxLoadGuestIntrState(pVCpu, uIntrState); 5961 return rc; 5962 } 5963 5964 5965 /** 5966 * Sets an invalid-opcode (#UD) exception as pending-for-injection into the VM. 5967 * 5804 5968 * @param pVCpu Pointer to the VMCPU. 5805 5969 * @param pMixedCtx Pointer to the guest-CPU context. The data may be 5806 5970 * out-of-sync. Make sure to update the required fields 5807 5971 * before using them. 5808 * 5809 * @remarks Must be called after hmR0VmxLoadGuestIntrState(). 5810 */ 5811 static int hmR0VmxInjectPendingInterrupt(PVM pVM, PVMCPU pVCpu, PCPUMCTX pMixedCtx) 5812 { 5813 /* First inject any pending HM interrupts. */ 5814 if (pVCpu->hm.s.Event.fPending) 5815 { 5816 Log(("Injecting pending event\n")); 5817 int rc = hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, pVCpu->hm.s.Event.u64IntrInfo, pVCpu->hm.s.Event.cbInstr, 5818 pVCpu->hm.s.Event.u32ErrCode); 5819 AssertRCReturn(rc, rc); 5820 pVCpu->hm.s.Event.fPending = false; 5821 return rc; 5822 } 5823 5824 /** @todo SMI. SMIs take priority over NMIs. */ 5825 5826 /* NMI. NMIs take priority over regular interrupts . */ 5827 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI)) 5828 { 5829 /* Construct an NMI interrupt and inject it into the VMCS. */ 5830 RTGCUINTPTR uIntrInfo; 5831 uIntrInfo = X86_XCPT_NMI; 5832 uIntrInfo |= (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT); 5833 uIntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5834 Log(("Injecting NMI\n")); 5835 int rc = hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, uIntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */); 5836 AssertRCReturn(rc, rc); 5837 return rc; 5838 } 5839 5840 /* We need the guests's RFLAGS for sure from this point on, make sure it is updated. */ 5841 int rc = hmR0VmxSaveGuestRflags(pVCpu, pMixedCtx); 5842 AssertRCReturn(rc, rc); 5843 5844 /* If there isn't any active trap, check if we have pending interrupts and convert them to TRPM traps and deliver them. */ 5845 if (!TRPMHasTrap(pVCpu)) 5846 { 5847 /* Check if there are guest external interrupts (PIC/APIC) pending. */ 5848 if (VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))) 5849 { 5850 /* 5851 * If the guest can receive interrupts now (interrupts enabled and no interrupt inhibition is active) convert 5852 * the PDM interrupt into a TRPM event and inject it. 5853 */ 5854 if ( (pMixedCtx->eflags.u32 & X86_EFL_IF) 5855 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)) 5856 { 5857 uint8_t u8Interrupt = 0; 5858 rc = PDMGetInterrupt(pVCpu, &u8Interrupt); 5859 if (RT_SUCCESS(rc)) 5860 { 5861 Log(("PDMGetInterrupt: u8Interrupt=%#x\n", u8Interrupt)); 5862 /* Convert pending interrupt from PIC/APIC into TRPM and handle it below. */ 5863 rc = TRPMAssertTrap(pVCpu, u8Interrupt, TRPM_HARDWARE_INT); 5864 AssertRCReturn(rc, rc); 5865 } 5866 else 5867 { 5868 /** @todo Does this actually happen? If not turn it into an assertion. */ 5869 Assert(!VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC))); 5870 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq); 5871 } 5872 } 5873 else if ( !(pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INT_WINDOW_EXIT) 5874 && (pVM->hm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INT_WINDOW_EXIT)) 5875 { 5876 /* Instruct VT-x to cause an interrupt-window exit as soon as the guest is ready to receive interrupts again. */ 5877 pVCpu->hm.s.vmx.u32ProcCtls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INT_WINDOW_EXIT; 5878 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC_CONTROLS, pVCpu->hm.s.vmx.u32ProcCtls); 5879 AssertRCReturn(rc, rc); 5880 } 5881 /* else we will deliver interrupts whenever the guest exits next and it's in a state to receive interrupts. */ 5882 } 5883 } 5884 5885 /* If interrupts can be delivered, inject it into the VM. */ 5886 if ( (pMixedCtx->eflags.u32 & X86_EFL_IF) 5887 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS) 5888 && TRPMHasTrap(pVCpu)) 5889 { 5890 Log(("Injecting TRPM trap\n")); 5891 rc = hmR0VmxInjectTRPMTrap(pVM, pVCpu, pMixedCtx); 5892 Assert(!TRPMHasTrap(pVCpu)); 5893 AssertRCReturn(rc, rc); 5894 } 5895 5896 /* 5897 * There's no need to clear the entry-interruption information field here if we're not injecting anything. VT-x clears the 5898 * valid bit on every VM-exit. See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection". 5899 */ 5900 return rc; 5901 } 5902 5903 /** 5904 * Sets an invalid-opcode (#UD) exception as pending-for-injection into the VM. 5972 */ 5973 DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPU pVCpu, PCPUMCTX pMixedCtx) 5974 { 5975 /* Refer Intel spec. 24.8.3 "VM-entry Controls for Event Injection" for the format of u32IntrInfo. */ 5976 uint32_t u32IntrInfo = X86_XCPT_UD | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT); 5977 STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject); 5978 hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */); 5979 } 5980 5981 5982 /** 5983 * Sets a double-fault (#DF) exception as pending-for-injection into the VM. 5984 * 5985 * @param pVCpu Pointer to the VMCPU. 5986 * @param pMixedCtx Pointer to the guest-CPU context. The data may be 5987 * out-of-sync. Make sure to update the required fields 5988 * before using them. 5989 */ 5990 DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPU pVCpu, PCPUMCTX pMixedCtx) 5991 { 5992 /* Inject the double-fault. */ 5993 uint32_t u32IntrInfo = X86_XCPT_DF | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT); 5994 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5995 u32IntrInfo |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID; 5996 STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject); 5997 hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */); 5998 } 5999 6000 6001 /** 6002 * Injects a double-fault (#DF) exception into the VM. 5905 6003 * 5906 6004 * @returns VBox status code (informational status code included). … … 5910 6008 * before using them. 5911 6009 */ 5912 DECLINLINE(int) hmR0VmxSetPendingXcptUD(PVMCPU pVCpu, PCPUMCTX pMixedCtx) 5913 { 5914 /* Refer Intel spec. 24.8.3 "VM-entry Controls for Event Injection" for the format of u32IntrInfo. */ 5915 uint32_t u32IntrInfo = X86_XCPT_UD | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT); 5916 STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject); 5917 hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */); 5918 return VINF_SUCCESS; 5919 } 5920 5921 5922 /** 5923 * Sets a double-fault (#DF) exception as pending-for-injection into the VM. 5924 * 5925 * @param pVCpu Pointer to the VMCPU. 5926 * @param pMixedCtx Pointer to the guest-CPU context. The data may be 5927 * out-of-sync. Make sure to update the required fields 5928 * before using them. 5929 */ 5930 DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPU pVCpu, PCPUMCTX pMixedCtx) 6010 DECLINLINE(int) hmR0VmxInjectXcptDF(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint32_t *puIntrState) 5931 6011 { 5932 6012 /* Inject the double-fault. */ … … 5935 6015 u32IntrInfo |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID; 5936 6016 STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject); 5937 hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */); 5938 } 5939 5940 5941 /** 5942 * Injects a double-fault (#DF) exception into the VM. 5943 * 5944 * @returns VBox status code (informational status code included). 6017 return hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, puIntrState); 6018 } 6019 6020 6021 /** 6022 * Sets a debug (#DB) exception as pending-for-injection into the VM. 6023 * 5945 6024 * @param pVCpu Pointer to the VMCPU. 5946 6025 * @param pMixedCtx Pointer to the guest-CPU context. The data may be … … 5948 6027 * before using them. 5949 6028 */ 5950 DECLINLINE(int) hmR0VmxInjectXcptDF(PVMCPU pVCpu, PCPUMCTX pMixedCtx) 5951 { 5952 /* Inject the double-fault. */ 5953 uint32_t u32IntrInfo = X86_XCPT_DF | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT); 5954 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5955 u32IntrInfo |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID; 5956 STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject); 5957 return hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */); 5958 } 5959 5960 5961 /** 5962 * Sets a debug (#DB) exception as pending-for-injection into the VM. 5963 * 5964 * @returns VBox status code (informational status code included). 5965 * @param pVCpu Pointer to the VMCPU. 5966 * @param pMixedCtx Pointer to the guest-CPU context. The data may be 5967 * out-of-sync. Make sure to update the required fields 5968 * before using them. 5969 */ 5970 DECLINLINE(int) hmR0VmxSetPendingXcptDB(PVMCPU pVCpu, PCPUMCTX pMixedCtx) 6029 DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPU pVCpu, PCPUMCTX pMixedCtx) 5971 6030 { 5972 6031 /* Inject the debug-exception. */ … … 5974 6033 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5975 6034 STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject); 5976 hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */); 5977 return VINF_SUCCESS; 6035 hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */); 5978 6036 } 5979 6037 … … 5982 6040 * Sets an overflow (#OF) exception as pending-for-injection into the VM. 5983 6041 * 5984 * @returns VBox status code (informational status code included).5985 6042 * @param pVCpu Pointer to the VMCPU. 5986 6043 * @param pMixedCtx Pointer to the guest-CPU context. The data may be … … 5990 6047 * stack. 5991 6048 */ 5992 DECLINLINE( int) hmR0VmxSetPendingXcptOF(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint32_t cbInstr)6049 DECLINLINE(void) hmR0VmxSetPendingXcptOF(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint32_t cbInstr) 5993 6050 { 5994 6051 /* Inject the overflow exception. */ … … 5996 6053 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 5997 6054 STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject); 5998 hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, cbInstr, 0 /* u32ErrCode */); 5999 return VINF_SUCCESS; 6055 hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, cbInstr, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */); 6000 6056 } 6001 6057 … … 6011 6067 * @param u32ErrorCode The error code associated with the #GP. 6012 6068 */ 6013 DECLINLINE(int) hmR0VmxInjectXcptGP(PVMCPU pVCpu, PCPUMCTX pMixedCtx, bool fErrorCodeValid, uint32_t u32ErrorCode) 6069 DECLINLINE(int) hmR0VmxInjectXcptGP(PVMCPU pVCpu, PCPUMCTX pMixedCtx, bool fErrorCodeValid, uint32_t u32ErrorCode, 6070 uint32_t *puIntrState) 6014 6071 { 6015 6072 /* Inject the general-protection fault. */ … … 6019 6076 u32IntrInfo |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID; 6020 6077 STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject); 6021 return hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */, u32ErrorCode); 6022 } 6023 6024 6025 /** 6026 * Injects a software interrupt (INTn) into the VM. 6027 * 6028 * @returns VBox status code (informational status code included). 6078 return hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */, u32ErrorCode, puIntrState); 6079 } 6080 6081 6082 /** 6083 * Sets a software interrupt (INTn) as pending-for-injection into the VM. 6084 * 6029 6085 * @param pVCpu Pointer to the VMCPU. 6030 6086 * @param pMixedCtx Pointer to the guest-CPU context. The data may be … … 6035 6091 * stack. 6036 6092 */ 6037 DECLINLINE( int) hmR0VmxInjectIntN(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint16_t uVector, uint32_t cbInstr)6093 DECLINLINE(void) hmR0VmxSetPendingIntN(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint16_t uVector, uint32_t cbInstr) 6038 6094 { 6039 6095 /* Inject the INTn. */ … … 6041 6097 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT); 6042 6098 STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject); 6043 hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, cbInstr, 0 /* u32ErrCode */); 6044 return VINF_SUCCESS; 6099 hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, cbInstr, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */); 6045 6100 } 6046 6101 … … 6091 6146 * 6092 6147 * @remarks No-long-jump zone!!! 6148 * @remarks Requires CR0! 6093 6149 */ 6094 6150 static int hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint64_t u64IntrInfo, uint32_t cbInstr, 6095 uint32_t u32ErrCode )6151 uint32_t u32ErrCode, uint32_t *puIntrState) 6096 6152 { 6097 6153 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */ 6098 6154 AssertMsg(u64IntrInfo >> 32 == 0, ("%#RX64\n", u64IntrInfo)); 6155 Assert(puIntrState); 6099 6156 uint32_t u32IntrInfo = (uint32_t)u64IntrInfo; 6157 6158 const uint32_t uVector = VMX_EXIT_INTERRUPTION_INFO_VECTOR(u32IntrInfo); 6159 const uint32_t uIntrType = VMX_EXIT_INTERRUPTION_INFO_TYPE(u32IntrInfo); 6160 6161 /* Cannot inject an NMI when block-by-MOV SS is in effect. */ 6162 Assert( uIntrType != VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI 6163 || !((*puIntrState) & VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_MOVSS)); 6164 6165 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]); 6100 6166 6101 6167 /* We require CR0 to check if the guest is in real-mode. */ … … 6103 6169 AssertRCReturn(rc, rc); 6104 6170 6105 const uint32_t uVector = VMX_EXIT_INTERRUPTION_INFO_VECTOR(u32IntrInfo);6106 6171 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]); 6107 6172 … … 6135 6200 { 6136 6201 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault. */ 6137 return hmR0VmxInjectXcptDF(pVCpu, pMixedCtx );6202 return hmR0VmxInjectXcptDF(pVCpu, pMixedCtx, puIntrState); 6138 6203 } 6139 6204 6140 6205 /* If we're injecting an interrupt/exception with no valid IDT entry, inject a general-protection fault. */ 6141 6206 /* No error codes for exceptions in real-mode. See Intel spec. 20.1.4 "Interrupt and Exception Handling" */ 6142 return hmR0VmxInjectXcptGP(pVCpu, pMixedCtx, false /* fErrCodeValid */, 0 /* u32ErrCode */ );6207 return hmR0VmxInjectXcptGP(pVCpu, pMixedCtx, false /* fErrCodeValid */, 0 /* u32ErrCode */, puIntrState); 6143 6208 } 6144 6209 … … 6179 6244 | HM_CHANGED_GUEST_RFLAGS 6180 6245 | HM_CHANGED_GUEST_RSP; 6246 6247 /* We're clearing interrupts, which means no block-by-STI interrupt-inhibition. */ 6248 if (*puIntrState & VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_STI) 6249 { 6250 Assert( uIntrType != VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI 6251 && uIntrType != VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT); 6252 Log(("Clearing inhibition due to STI.\n")); 6253 *puIntrState &= ~VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_STI; 6254 } 6255 Log(("Injecting u32IntrInfo=%#x u32ErrCode=%#x instrlen=%#x\n", u32IntrInfo, u32ErrCode, cbInstr)); 6181 6256 } 6182 6257 Assert(rc == VINF_SUCCESS || rc == VINF_EM_RESET); … … 6199 6274 Assert(!(u32IntrInfo & 0x7ffff000)); /* Bits 30:12 MBZ. */ 6200 6275 Log(("Injecting u32IntrInfo=%#x u32ErrCode=%#x instrlen=%#x\n", u32IntrInfo, u32ErrCode, cbInstr)); 6201 6202 6276 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntrInfo); 6203 6277 if (VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_IS_VALID(u32IntrInfo)) … … 6205 6279 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr); 6206 6280 AssertRCReturn(rc, rc); 6281 6282 Assert(uIntrType != VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_INT); 6207 6283 return rc; 6208 6284 } … … 6466 6542 * This is why this is done after all possible exits-to-ring-3 paths in this code. 6467 6543 */ 6468 hmR0VmxLoadGuestIntrState(pVM, pVCpu, pMixedCtx); 6469 rc = hmR0VmxInjectPendingInterrupt(pVM, pVCpu, pMixedCtx); 6544 rc = hmR0VmxInjectEvent(pVCpu, pMixedCtx); 6470 6545 AssertRCReturn(rc, rc); 6471 6546 return rc; … … 6662 6737 int rc = VERR_INTERNAL_ERROR_5; 6663 6738 uint32_t cLoops = 0; 6739 hmR0VmxUpdatePendingEvent(pVCpu, pCtx); 6664 6740 6665 6741 for (;; cLoops++) … … 6704 6780 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatExit1, &pVCpu->hm.s.StatExit2, x); 6705 6781 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason)); 6706 rc = (* s_apfnVMExitHandlers[VmxTransient.uExitReason])(pVCpu, pCtx, &VmxTransient);6782 rc = (*g_apfnVMExitHandlers[VmxTransient.uExitReason])(pVCpu, pCtx, &VmxTransient); 6707 6783 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExit2, x); 6708 6784 if (rc != VINF_SUCCESS) … … 6875 6951 { 6876 6952 VMX_VALIDATE_EXIT_HANDLER_PARAMS(); 6953 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3); 6954 6877 6955 int rc = hmR0VmxReadExitIntrInfoVmcs(pVCpu, pVmxTransient); 6878 6956 AssertRCReturn(rc, rc); … … 6883 6961 6884 6962 if (uIntrType == VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI) 6963 { 6964 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3); 6885 6965 return VINF_EM_RAW_INTERRUPT; 6966 } 6886 6967 6887 6968 /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */ 6888 6969 rc = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pMixedCtx, pVmxTransient); 6889 6970 if (RT_UNLIKELY(rc == VINF_VMX_DOUBLE_FAULT)) 6971 { 6972 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3); 6890 6973 return VINF_SUCCESS; 6974 } 6891 6975 else if (RT_UNLIKELY(rc == VINF_EM_RESET)) 6976 { 6977 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3); 6892 6978 return rc; 6979 } 6893 6980 6894 6981 uint32_t uExitIntrInfo = pVmxTransient->uExitIntrInfo; … … 6935 7022 AssertRCReturn(rc, rc); 6936 7023 hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(uExitIntrInfo), 6937 pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode); 7024 pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode, 7025 0 /* GCPtrFaultAddress */); 6938 7026 AssertRCReturn(rc, rc); 6939 7027 } … … 6957 7045 } 6958 7046 } 7047 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3); 6959 7048 return rc; 6960 7049 } … … 6974 7063 AssertRCReturn(rc, rc); 6975 7064 6976 /* Deliver the pending interrupt via hmR0VmxPreRunGuest()->hmR0VmxInject PendingInterrupt() and resume guest execution. */7065 /* Deliver the pending interrupt via hmR0VmxPreRunGuest()->hmR0VmxInjectEvent() and resume guest execution. */ 6977 7066 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow); 6978 7067 return VINF_SUCCESS; … … 7562 7651 } 7563 7652 } 7564 #ifdef DEBUG7653 #ifdef VBOX_STRICT 7565 7654 else 7566 7655 { … … 7637 7726 /* 7638 7727 * The TPR has already been updated, see hmR0VMXPostRunGuest(). RIP is also updated as part of the VM-exit by VT-x. Update 7639 * the threshold in the VMCS, deliver the pending interrupt via hmR0VmxPreRunGuest()->hmR0VmxInject PendingInterrupt() and7728 * the threshold in the VMCS, deliver the pending interrupt via hmR0VmxPreRunGuest()->hmR0VmxInjectEvent() and 7640 7729 * resume guest execution. 7641 7730 */ … … 7927 8016 7928 8017 /* Set #DB to be injected into the VM and continue guest execution. */ 7929 rc = hmR0VmxSetPendingXcptDB(pVCpu, pMixedCtx); 7930 AssertRCReturn(rc, rc); 8018 hmR0VmxSetPendingXcptDB(pVCpu, pMixedCtx); 7931 8019 break; 7932 8020 } … … 8257 8345 uErrorCode |= X86_TRAP_PF_P; 8258 8346 8259 TRPMAssertTrap(pVCpu, X86_XCPT_PF, TRPM_TRAP); 8260 TRPMSetErrorCode(pVCpu, uErrorCode); 8261 TRPMSetFaultAddress(pVCpu, GCPhys); 8347 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode); 8262 8348 8263 8349 Log(("EPT violation %#x at %#RGv ErrorCode %#x CS:EIP=%04x:%#RX64\n", (uint32_t)pVmxTransient->uExitQualification, GCPhys, … … 8307 8393 } 8308 8394 hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo), 8309 pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode );8395 pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode, 0 /* GCPtrFaultAddress */); 8310 8396 return rc; 8311 8397 } … … 8335 8421 8336 8422 hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo), 8337 pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode );8423 pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode, 0 /* GCPtrFaultAddress */); 8338 8424 } 8339 8425 … … 8386 8472 AssertRCReturn(rc,rc); 8387 8473 hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo), 8388 pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode );8474 pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode, 0 /* GCPtrFaultAddress */); 8389 8475 return rc; 8390 8476 } … … 8426 8512 AssertRCReturn(rc, rc); 8427 8513 hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo), 8428 pVmxTransient->cbInstr, 0 /* error code */ );8514 pVmxTransient->cbInstr, 0 /* error code */, 0 /* GCPtrFaultAddress */); 8429 8515 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNM); 8430 8516 return rc; … … 8454 8540 Log(("#GP Gst: RIP %#RX64\n", pMixedCtx->rip)); 8455 8541 hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo), 8456 pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode );8542 pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode, 0 /* GCPtrFaultAddress */); 8457 8543 return rc; 8458 8544 #else … … 8633 8719 { 8634 8720 uint16_t uVector = pDis->Param1.uValue & 0xff; 8635 rc = hmR0VmxInjectIntN(pVCpu, pMixedCtx, uVector, pDis->cbInstr); 8636 AssertRCReturn(rc, rc); 8721 hmR0VmxSetPendingIntN(pVCpu, pMixedCtx, uVector, pDis->cbInstr); 8637 8722 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitInt); 8638 8723 break; … … 8643 8728 if (pMixedCtx->eflags.Bits.u1OF) 8644 8729 { 8645 rc =hmR0VmxSetPendingXcptOF(pVCpu, pMixedCtx, pDis->cbInstr);8730 hmR0VmxSetPendingXcptOF(pVCpu, pMixedCtx, pDis->cbInstr); 8646 8731 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitInt); 8647 8732 } … … 8683 8768 hmR0VmxCheckExitDueToEventDelivery(). */ 8684 8769 hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo), 8685 pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode );8770 pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode, 0 /* GCPtrFaultAddress */); 8686 8771 return VINF_SUCCESS; 8687 8772 } … … 8708 8793 pMixedCtx->cr2 = pVmxTransient->uExitQualification; 8709 8794 hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo), 8710 pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode );8795 pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode, pMixedCtx->cr2); 8711 8796 } 8712 8797 else … … 8753 8838 #endif 8754 8839 8755 TRPMAssertTrap(pVCpu, X86_XCPT_PF, TRPM_TRAP);8756 TRPMSetFaultAddress(pVCpu, pVmxTransient->uExitQualification);8757 TRPMSetErrorCode(pVCpu, pVmxTransient->uExitIntrErrorCode);8758 8759 8840 rc = hmR0VmxSaveGuestState(pVCpu, pMixedCtx); 8760 8841 AssertRCReturn(rc, rc); 8842 8843 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQualification, (RTGCUINT)pVmxTransient->uExitIntrErrorCode); 8761 8844 8762 8845 /* Forward it to the trap handler first. */ … … 8787 8870 pMixedCtx->cr2 = pVmxTransient->uExitQualification; 8788 8871 hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo), 8789 pVmxTransient->cbInstr, uGstErrorCode );8872 pVmxTransient->cbInstr, uGstErrorCode, pMixedCtx->cr2); 8790 8873 } 8791 8874 else -
trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp
r45503 r45531 675 675 { 676 676 uint8_t u8Vector; 677 rc = TRPMQueryTrapAll(pVCpu, &u8Vector, 0, 0, 0);677 rc = TRPMQueryTrapAll(pVCpu, &u8Vector, 0, NULL, NULL, NULL); 678 678 AssertRC(rc); 679 679 } … … 693 693 694 694 /* If a new event is pending, then dispatch it now. */ 695 rc = TRPMQueryTrapAll(pVCpu, &u8Vector, &enmType, &u32ErrorCode, 0);695 rc = TRPMQueryTrapAll(pVCpu, &u8Vector, &enmType, &u32ErrorCode, NULL, NULL); 696 696 AssertRC(rc); 697 697 Assert(pCtx->eflags.Bits.u1IF == 1 || enmType == TRPM_TRAP); -
trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp
r45517 r45531 1171 1171 { 1172 1172 uint8_t u8Vector; 1173 rc = TRPMQueryTrapAll(pVCpu, &u8Vector, 0, 0, 0);1173 rc = TRPMQueryTrapAll(pVCpu, &u8Vector, 0, NULL, NULL, NULL); 1174 1174 AssertRC(rc); 1175 1175 } … … 1189 1189 * If a new event is pending, dispatch it now. 1190 1190 */ 1191 rc = TRPMQueryTrapAll(pVCpu, &u8Vector, &enmType, &errCode, 0);1191 rc = TRPMQueryTrapAll(pVCpu, &u8Vector, &enmType, &errCode, NULL, NULL); 1192 1192 AssertRC(rc); 1193 1193 Assert(pCtx->eflags.Bits.u1IF == 1 || enmType == TRPM_TRAP); -
trunk/src/VBox/VMM/VMMR3/EMRaw.cpp
r45485 r45531 518 518 RTGCUINT uErrorCode; 519 519 RTGCUINTPTR uCR2; 520 int rc = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2 );520 int rc = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2, NULL /* pu8InstrLen */); 521 521 if (RT_FAILURE(rc)) 522 522 { … … 754 754 else 755 755 { 756 rc = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2 );756 rc = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2, NULL /* pu8InstrLen */); 757 757 if (RT_FAILURE(rc)) 758 758 { -
trunk/src/VBox/VMM/VMMR3/HM.cpp
r45528 r45531 67 67 EXIT_REASON(VMX_EXIT_IO_SMI_IRQ , 5, "I/O system-management interrupt (SMI)."), 68 68 EXIT_REASON(VMX_EXIT_SMI_IRQ , 6, "Other SMI."), 69 EXIT_REASON(VMX_EXIT_I RQ_WINDOW , 7, "Interrupt window."),69 EXIT_REASON(VMX_EXIT_INT_WINDOW , 7, "Interrupt window."), 70 70 EXIT_REASON_NIL(), 71 71 EXIT_REASON(VMX_EXIT_TASK_SWITCH , 9, "Task switch."), … … 111 111 EXIT_REASON(VMX_EXIT_EPT_MISCONFIG , 49, "EPT misconfiguration. An attempt to access memory with a guest-physical address encountered a misconfigured EPT paging-structure entry."), 112 112 EXIT_REASON(VMX_EXIT_INVEPT , 50, "INVEPT. Guest software attempted to execute INVEPT."), 113 EXIT_REASON(VMX_EXIT_RDTSCP , 51, " Guest software attempted to execute RDTSCP."),114 EXIT_REASON(VMX_EXIT_PREEMPT_TIMER , 52, "VMX-preemption timer expired. The preemption timer counted down to zero."),113 EXIT_REASON(VMX_EXIT_RDTSCP , 51, "RDTSCP. Guest software attempted to execute RDTSCP."), 114 EXIT_REASON(VMX_EXIT_PREEMPT_TIMER , 52, "VMX-preemption timer expired."), 115 115 EXIT_REASON(VMX_EXIT_INVVPID , 53, "INVVPID. Guest software attempted to execute INVVPID."), 116 116 EXIT_REASON(VMX_EXIT_WBINVD , 54, "WBINVD. Guest software attempted to execute WBINVD."), -
trunk/src/VBox/VMM/VMMR3/VMMGuruMeditation.cpp
r44528 r45531 300 300 RTGCUINT uErrorCode = 0xdeadface; 301 301 RTGCUINTPTR uCR2 = 0xdeadface; 302 int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2); 302 uint8_t cbInstr = UINT8_MAX; 303 int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2, &cbInstr); 303 304 if (!HMIsEnabled(pVM)) 304 305 { 305 306 if (RT_SUCCESS(rc2)) 306 307 pHlp->pfnPrintf(pHlp, 307 "!! TRAP=%02x ERRCD=%RGv CR2=%RGv EIP=%RX32 Type=%d \n",308 u8TrapNo, uErrorCode, uCR2, uEIP, enmType );308 "!! TRAP=%02x ERRCD=%RGv CR2=%RGv EIP=%RX32 Type=%d cbInstr=%02x\n", 309 u8TrapNo, uErrorCode, uCR2, uEIP, enmType, cbInstr); 309 310 else 310 311 pHlp->pfnPrintf(pHlp, … … 314 315 else if (RT_SUCCESS(rc2)) 315 316 pHlp->pfnPrintf(pHlp, 316 "!! ACTIVE TRAP=%02x ERRCD=%RGv CR2=%RGv PC=%RGr Type=%d (Guest!)\n",317 u8TrapNo, uErrorCode, uCR2, CPUMGetGuestRIP(pVCpu), enmType );317 "!! ACTIVE TRAP=%02x ERRCD=%RGv CR2=%RGv PC=%RGr Type=%d cbInstr=%02x (Guest!)\n", 318 u8TrapNo, uErrorCode, uCR2, CPUMGetGuestRIP(pVCpu), enmType, cbInstr); 318 319 319 320 /* -
trunk/src/VBox/VMM/include/HMInternal.h
r45517 r45531 734 734 uint32_t u32Padding; /**< Explicit alignment padding. */ 735 735 uint64_t u64IntrInfo; 736 RTGCUINTPTR GCPtrFaultAddress; 736 737 } Event; 737 738 -
trunk/src/VBox/VMM/include/TRPMInternal.h
r43872 r45531 234 234 /** Previous trap vector # - for debugging. */ 235 235 RTGCUINT uPrevVector; 236 237 /** Instruction length for software interrupts and software exceptions (#BP, 238 * #OF) */ 239 uint8_t cbInstr; 240 241 /** Saved instruction length. */ 242 uint8_t cbSavedInstr; 243 244 /** Padding. */ 245 uint8_t au8Padding[2]; 236 246 } TRPMCPU; 237 247 -
trunk/src/VBox/VMM/include/TRPMInternal.mac
r41943 r45531 80 80 .uSavedCR2 RTGCPTR_RES 1 81 81 .uPrevVector RTGCPTR_RES 1 82 .cbInstr resb 1 83 .cbSavedInstr resb 1 84 .au8Padding resb 2 82 85 endstruc 83 86
Note:
See TracChangeset
for help on using the changeset viewer.