Changeset 93748 in vbox for trunk/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h
- Timestamp:
- Feb 15, 2022 12:20:46 PM (3 years ago)
- svn:sync-xref-src-repo-rev:
- 149931
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h
r93583 r93748 10212 10212 #endif /* VBOX_WITH_NESTED_HWVIRT_VMX */ 10213 10213 10214 10215 /** @name Execution loop for single stepping, DBGF events and expensive Dtrace 10216 * probes. 10217 * 10218 * The following few functions and associated structure contains the bloat 10219 * necessary for providing detailed debug events and dtrace probes as well as 10220 * reliable host side single stepping. This works on the principle of 10221 * "subclassing" the normal execution loop and workers. We replace the loop 10222 * method completely and override selected helpers to add necessary adjustments 10223 * to their core operation. 10224 * 10225 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice 10226 * any performance for debug and analysis features. 10227 * 10228 * @{ 10229 */ 10230 10231 /** 10232 * Transient per-VCPU debug state of VMCS and related info. we save/restore in 10233 * the debug run loop. 10234 */ 10235 typedef struct VMXRUNDBGSTATE 10236 { 10237 /** The RIP we started executing at. This is for detecting that we stepped. */ 10238 uint64_t uRipStart; 10239 /** The CS we started executing with. */ 10240 uint16_t uCsStart; 10241 10242 /** Whether we've actually modified the 1st execution control field. */ 10243 bool fModifiedProcCtls : 1; 10244 /** Whether we've actually modified the 2nd execution control field. */ 10245 bool fModifiedProcCtls2 : 1; 10246 /** Whether we've actually modified the exception bitmap. */ 10247 bool fModifiedXcptBitmap : 1; 10248 10249 /** We desire the modified the CR0 mask to be cleared. */ 10250 bool fClearCr0Mask : 1; 10251 /** We desire the modified the CR4 mask to be cleared. */ 10252 bool fClearCr4Mask : 1; 10253 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */ 10254 uint32_t fCpe1Extra; 10255 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */ 10256 uint32_t fCpe1Unwanted; 10257 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */ 10258 uint32_t fCpe2Extra; 10259 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */ 10260 uint32_t bmXcptExtra; 10261 /** The sequence number of the Dtrace provider settings the state was 10262 * configured against. */ 10263 uint32_t uDtraceSettingsSeqNo; 10264 /** VM-exits to check (one bit per VM-exit). */ 10265 uint32_t bmExitsToCheck[3]; 10266 10267 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */ 10268 uint32_t fProcCtlsInitial; 10269 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */ 10270 uint32_t fProcCtls2Initial; 10271 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */ 10272 uint32_t bmXcptInitial; 10273 } VMXRUNDBGSTATE; 10274 AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4); 10275 typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE; 10276 10277 10278 /** 10279 * Initializes the VMXRUNDBGSTATE structure. 10280 * 10281 * @param pVCpu The cross context virtual CPU structure of the 10282 * calling EMT. 10283 * @param pVmxTransient The VMX-transient structure. 10284 * @param pDbgState The debug state to initialize. 10285 */ 10286 static void vmxHCRunDebugStateInit(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState) 10287 { 10288 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip; 10289 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel; 10290 10291 pDbgState->fModifiedProcCtls = false; 10292 pDbgState->fModifiedProcCtls2 = false; 10293 pDbgState->fModifiedXcptBitmap = false; 10294 pDbgState->fClearCr0Mask = false; 10295 pDbgState->fClearCr4Mask = false; 10296 pDbgState->fCpe1Extra = 0; 10297 pDbgState->fCpe1Unwanted = 0; 10298 pDbgState->fCpe2Extra = 0; 10299 pDbgState->bmXcptExtra = 0; 10300 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls; 10301 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2; 10302 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap; 10303 } 10304 10305 10306 /** 10307 * Updates the VMSC fields with changes requested by @a pDbgState. 10308 * 10309 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well 10310 * immediately before executing guest code, i.e. when interrupts are disabled. 10311 * We don't check status codes here as we cannot easily assert or return in the 10312 * latter case. 10313 * 10314 * @param pVCpu The cross context virtual CPU structure. 10315 * @param pVmxTransient The VMX-transient structure. 10316 * @param pDbgState The debug state. 10317 */ 10318 static void vmxHCPreRunGuestDebugStateApply(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState) 10319 { 10320 /* 10321 * Ensure desired flags in VMCS control fields are set. 10322 * (Ignoring write failure here, as we're committed and it's just debug extras.) 10323 * 10324 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so 10325 * there should be no stale data in pCtx at this point. 10326 */ 10327 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 10328 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra 10329 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted)) 10330 { 10331 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra; 10332 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted; 10333 VMX_VMCS_WRITE_32(pVCpu, VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls); 10334 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls)); 10335 pDbgState->fModifiedProcCtls = true; 10336 } 10337 10338 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra) 10339 { 10340 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra; 10341 VMX_VMCS_WRITE_32(pVCpu, VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2); 10342 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2)); 10343 pDbgState->fModifiedProcCtls2 = true; 10344 } 10345 10346 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra) 10347 { 10348 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra; 10349 VMX_VMCS_WRITE_32(pVCpu, VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap); 10350 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap)); 10351 pDbgState->fModifiedXcptBitmap = true; 10352 } 10353 10354 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0) 10355 { 10356 pVmcsInfo->u64Cr0Mask = 0; 10357 VMX_VMCS_WRITE_NW(pVCpu, VMX_VMCS_CTRL_CR0_MASK, 0); 10358 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n")); 10359 } 10360 10361 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0) 10362 { 10363 pVmcsInfo->u64Cr4Mask = 0; 10364 VMX_VMCS_WRITE_NW(pVCpu, VMX_VMCS_CTRL_CR4_MASK, 0); 10365 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n")); 10366 } 10367 10368 NOREF(pVCpu); 10369 } 10370 10371 10372 /** 10373 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for 10374 * re-entry next time around. 10375 * 10376 * @returns Strict VBox status code (i.e. informational status codes too). 10377 * @param pVCpu The cross context virtual CPU structure. 10378 * @param pVmxTransient The VMX-transient structure. 10379 * @param pDbgState The debug state. 10380 * @param rcStrict The return code from executing the guest using single 10381 * stepping. 10382 */ 10383 static VBOXSTRICTRC vmxHCRunDebugStateRevert(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState, 10384 VBOXSTRICTRC rcStrict) 10385 { 10386 /* 10387 * Restore VM-exit control settings as we may not reenter this function the 10388 * next time around. 10389 */ 10390 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo; 10391 10392 /* We reload the initial value, trigger what we can of recalculations the 10393 next time around. From the looks of things, that's all that's required atm. */ 10394 if (pDbgState->fModifiedProcCtls) 10395 { 10396 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu)) 10397 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */ 10398 int rc2 = VMX_VMCS_WRITE_32(pVCpu, VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial); 10399 AssertRC(rc2); 10400 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial; 10401 } 10402 10403 /* We're currently the only ones messing with this one, so just restore the 10404 cached value and reload the field. */ 10405 if ( pDbgState->fModifiedProcCtls2 10406 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial) 10407 { 10408 int rc2 = VMX_VMCS_WRITE_32(pVCpu, VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial); 10409 AssertRC(rc2); 10410 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial; 10411 } 10412 10413 /* If we've modified the exception bitmap, we restore it and trigger 10414 reloading and partial recalculation the next time around. */ 10415 if (pDbgState->fModifiedXcptBitmap) 10416 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial; 10417 10418 return rcStrict; 10419 } 10420 10421 10422 /** 10423 * Configures VM-exit controls for current DBGF and DTrace settings. 10424 * 10425 * This updates @a pDbgState and the VMCS execution control fields to reflect 10426 * the necessary VM-exits demanded by DBGF and DTrace. 10427 * 10428 * @param pVCpu The cross context virtual CPU structure. 10429 * @param pVmxTransient The VMX-transient structure. May update 10430 * fUpdatedTscOffsettingAndPreemptTimer. 10431 * @param pDbgState The debug state. 10432 */ 10433 static void vmxHCPreRunGuestDebugStateUpdate(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState) 10434 { 10435 #ifndef IN_NEM_DARWIN 10436 /* 10437 * Take down the dtrace serial number so we can spot changes. 10438 */ 10439 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO(); 10440 ASMCompilerBarrier(); 10441 #endif 10442 10443 /* 10444 * We'll rebuild most of the middle block of data members (holding the 10445 * current settings) as we go along here, so start by clearing it all. 10446 */ 10447 pDbgState->bmXcptExtra = 0; 10448 pDbgState->fCpe1Extra = 0; 10449 pDbgState->fCpe1Unwanted = 0; 10450 pDbgState->fCpe2Extra = 0; 10451 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++) 10452 pDbgState->bmExitsToCheck[i] = 0; 10453 10454 /* 10455 * Software interrupts (INT XXh) - no idea how to trigger these... 10456 */ 10457 PVMCC pVM = pVCpu->CTX_SUFF(pVM); 10458 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE) 10459 || VBOXVMM_INT_SOFTWARE_ENABLED()) 10460 { 10461 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI); 10462 } 10463 10464 /* 10465 * INT3 breakpoints - triggered by #BP exceptions. 10466 */ 10467 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0) 10468 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP); 10469 10470 /* 10471 * Exception bitmap and XCPT events+probes. 10472 */ 10473 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++) 10474 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt))) 10475 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt); 10476 10477 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE); 10478 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB); 10479 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP); 10480 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF); 10481 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR); 10482 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD); 10483 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM); 10484 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF); 10485 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS); 10486 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP); 10487 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS); 10488 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP); 10489 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF); 10490 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF); 10491 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC); 10492 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF); 10493 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE); 10494 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX); 10495 10496 if (pDbgState->bmXcptExtra) 10497 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI); 10498 10499 /* 10500 * Process events and probes for VM-exits, making sure we get the wanted VM-exits. 10501 * 10502 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does. 10503 * So, when adding/changing/removing please don't forget to update it. 10504 * 10505 * Some of the macros are picking up local variables to save horizontal space, 10506 * (being able to see it in a table is the lesser evil here). 10507 */ 10508 #define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \ 10509 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \ 10510 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() ) 10511 #define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \ 10512 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \ 10513 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \ 10514 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \ 10515 } else do { } while (0) 10516 #define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \ 10517 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \ 10518 { \ 10519 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \ 10520 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \ 10521 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \ 10522 } else do { } while (0) 10523 #define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \ 10524 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \ 10525 { \ 10526 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \ 10527 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \ 10528 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \ 10529 } else do { } while (0) 10530 #define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \ 10531 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \ 10532 { \ 10533 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \ 10534 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \ 10535 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \ 10536 } else do { } while (0) 10537 10538 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */ 10539 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */ 10540 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */ 10541 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */ 10542 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */ 10543 10544 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */ 10545 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID); 10546 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */ 10547 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC); 10548 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */ 10549 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT); 10550 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */ 10551 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD); 10552 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT); 10553 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG); 10554 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT); 10555 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC); 10556 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT); 10557 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC); 10558 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */ 10559 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM); 10560 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */ 10561 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL); 10562 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */ 10563 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); 10564 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */ 10565 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); 10566 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */ 10567 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); 10568 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */ 10569 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST); 10570 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */ 10571 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD); 10572 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */ 10573 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME); 10574 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */ 10575 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE); 10576 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */ 10577 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF); 10578 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */ 10579 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON); 10580 10581 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ) 10582 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE)) 10583 { 10584 int rc = vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4 10585 | CPUMCTX_EXTRN_APIC_TPR); 10586 AssertRC(rc); 10587 10588 #if 0 /** @todo fix me */ 10589 pDbgState->fClearCr0Mask = true; 10590 pDbgState->fClearCr4Mask = true; 10591 #endif 10592 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)) 10593 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT; 10594 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE)) 10595 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT; 10596 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */ 10597 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would 10598 require clearing here and in the loop if we start using it. */ 10599 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX); 10600 } 10601 else 10602 { 10603 if (pDbgState->fClearCr0Mask) 10604 { 10605 pDbgState->fClearCr0Mask = false; 10606 ASMAtomicUoOrU64(&VCPU_2_VMXSTATE(pVCpu).fCtxChanged, HM_CHANGED_GUEST_CR0); 10607 } 10608 if (pDbgState->fClearCr4Mask) 10609 { 10610 pDbgState->fClearCr4Mask = false; 10611 ASMAtomicUoOrU64(&VCPU_2_VMXSTATE(pVCpu).fCtxChanged, HM_CHANGED_GUEST_CR4); 10612 } 10613 } 10614 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX); 10615 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX); 10616 10617 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ) 10618 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE)) 10619 { 10620 /** @todo later, need to fix handler as it assumes this won't usually happen. */ 10621 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX); 10622 } 10623 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX); 10624 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX); 10625 10626 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */ 10627 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR); 10628 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); 10629 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR); 10630 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */ 10631 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT); 10632 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */ 10633 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR); 10634 #if 0 /** @todo too slow, fix handler. */ 10635 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT); 10636 #endif 10637 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE); 10638 10639 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT) 10640 || IS_EITHER_ENABLED(pVM, INSTR_SIDT) 10641 || IS_EITHER_ENABLED(pVM, INSTR_LGDT) 10642 || IS_EITHER_ENABLED(pVM, INSTR_LIDT)) 10643 { 10644 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT; 10645 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS); 10646 } 10647 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS); 10648 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS); 10649 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS); 10650 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS); 10651 10652 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT) 10653 || IS_EITHER_ENABLED(pVM, INSTR_STR) 10654 || IS_EITHER_ENABLED(pVM, INSTR_LLDT) 10655 || IS_EITHER_ENABLED(pVM, INSTR_LTR)) 10656 { 10657 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT; 10658 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS); 10659 } 10660 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS); 10661 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS); 10662 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS); 10663 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS); 10664 10665 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */ 10666 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT); 10667 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT); 10668 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP); 10669 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */ 10670 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID); 10671 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT); 10672 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD); 10673 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */ 10674 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV); 10675 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT); 10676 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND); 10677 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT); 10678 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID); 10679 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */ 10680 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC); 10681 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT); 10682 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED); 10683 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */ 10684 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES); 10685 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */ 10686 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS); 10687 10688 #undef IS_EITHER_ENABLED 10689 #undef SET_ONLY_XBM_IF_EITHER_EN 10690 #undef SET_CPE1_XBM_IF_EITHER_EN 10691 #undef SET_CPEU_XBM_IF_EITHER_EN 10692 #undef SET_CPE2_XBM_IF_EITHER_EN 10693 10694 /* 10695 * Sanitize the control stuff. 10696 */ 10697 pDbgState->fCpe2Extra &= g_HmMsrs.u.vmx.ProcCtls2.n.allowed1; 10698 if (pDbgState->fCpe2Extra) 10699 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS; 10700 pDbgState->fCpe1Extra &= g_HmMsrs.u.vmx.ProcCtls.n.allowed1; 10701 pDbgState->fCpe1Unwanted &= ~g_HmMsrs.u.vmx.ProcCtls.n.allowed0; 10702 #ifndef IN_NEM_DARWIN /** @todo */ 10703 if (pVCpu->hmr0.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT)) 10704 { 10705 pVCpu->hmr0.s.fDebugWantRdTscExit ^= true; 10706 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false; 10707 } 10708 #endif 10709 10710 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n", 10711 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra, 10712 pDbgState->fClearCr0Mask ? " clr-cr0" : "", 10713 pDbgState->fClearCr4Mask ? " clr-cr4" : "")); 10714 } 10715 10716 10717 /** 10718 * Fires off DBGF events and dtrace probes for a VM-exit, when it's 10719 * appropriate. 10720 * 10721 * The caller has checked the VM-exit against the 10722 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs 10723 * already, so we don't have to do that either. 10724 * 10725 * @returns Strict VBox status code (i.e. informational status codes too). 10726 * @param pVCpu The cross context virtual CPU structure. 10727 * @param pVmxTransient The VMX-transient structure. 10728 * @param uExitReason The VM-exit reason. 10729 * 10730 * @remarks The name of this function is displayed by dtrace, so keep it short 10731 * and to the point. No longer than 33 chars long, please. 10732 */ 10733 static VBOXSTRICTRC vmxHCHandleExitDtraceEvents(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason) 10734 { 10735 /* 10736 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the 10737 * same time check whether any corresponding Dtrace event is enabled (fDtrace). 10738 * 10739 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate 10740 * does. Must add/change/remove both places. Same ordering, please. 10741 * 10742 * Added/removed events must also be reflected in the next section 10743 * where we dispatch dtrace events. 10744 */ 10745 bool fDtrace1 = false; 10746 bool fDtrace2 = false; 10747 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END; 10748 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END; 10749 uint32_t uEventArg = 0; 10750 #define SET_EXIT(a_EventSubName) \ 10751 do { \ 10752 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \ 10753 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \ 10754 } while (0) 10755 #define SET_BOTH(a_EventSubName) \ 10756 do { \ 10757 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \ 10758 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \ 10759 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \ 10760 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \ 10761 } while (0) 10762 switch (uExitReason) 10763 { 10764 case VMX_EXIT_MTF: 10765 return vmxHCExitMtf(pVCpu, pVmxTransient); 10766 10767 case VMX_EXIT_XCPT_OR_NMI: 10768 { 10769 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo); 10770 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo)) 10771 { 10772 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT: 10773 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT: 10774 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT: 10775 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST)) 10776 { 10777 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo)) 10778 { 10779 vmxHCReadExitIntErrorCodeVmcs(pVCpu, pVmxTransient); 10780 uEventArg = pVmxTransient->uExitIntErrorCode; 10781 } 10782 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector); 10783 switch (enmEvent1) 10784 { 10785 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break; 10786 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break; 10787 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break; 10788 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break; 10789 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break; 10790 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break; 10791 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break; 10792 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break; 10793 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break; 10794 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break; 10795 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break; 10796 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break; 10797 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break; 10798 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break; 10799 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break; 10800 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break; 10801 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break; 10802 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break; 10803 default: break; 10804 } 10805 } 10806 else 10807 AssertFailed(); 10808 break; 10809 10810 case VMX_EXIT_INT_INFO_TYPE_SW_INT: 10811 uEventArg = idxVector; 10812 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE; 10813 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED(); 10814 break; 10815 } 10816 break; 10817 } 10818 10819 case VMX_EXIT_TRIPLE_FAULT: 10820 enmEvent1 = DBGFEVENT_TRIPLE_FAULT; 10821 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED(); 10822 break; 10823 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break; 10824 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break; 10825 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break; 10826 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break; 10827 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break; 10828 10829 /* Instruction specific VM-exits: */ 10830 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break; 10831 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break; 10832 case VMX_EXIT_HLT: SET_BOTH(HALT); break; 10833 case VMX_EXIT_INVD: SET_BOTH(INVD); break; 10834 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break; 10835 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break; 10836 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break; 10837 case VMX_EXIT_RSM: SET_BOTH(RSM); break; 10838 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break; 10839 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break; 10840 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break; 10841 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break; 10842 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break; 10843 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break; 10844 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break; 10845 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break; 10846 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break; 10847 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break; 10848 case VMX_EXIT_MOV_CRX: 10849 vmxHCReadExitQualVmcs(pVCpu, pVmxTransient); 10850 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ) 10851 SET_BOTH(CRX_READ); 10852 else 10853 SET_BOTH(CRX_WRITE); 10854 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual); 10855 break; 10856 case VMX_EXIT_MOV_DRX: 10857 vmxHCReadExitQualVmcs(pVCpu, pVmxTransient); 10858 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) 10859 == VMX_EXIT_QUAL_DRX_DIRECTION_READ) 10860 SET_BOTH(DRX_READ); 10861 else 10862 SET_BOTH(DRX_WRITE); 10863 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual); 10864 break; 10865 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break; 10866 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break; 10867 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break; 10868 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break; 10869 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break; 10870 case VMX_EXIT_GDTR_IDTR_ACCESS: 10871 vmxHCReadExitInstrInfoVmcs(pVCpu, pVmxTransient); 10872 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID)) 10873 { 10874 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break; 10875 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break; 10876 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break; 10877 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break; 10878 } 10879 break; 10880 10881 case VMX_EXIT_LDTR_TR_ACCESS: 10882 vmxHCReadExitInstrInfoVmcs(pVCpu, pVmxTransient); 10883 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID)) 10884 { 10885 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break; 10886 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break; 10887 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break; 10888 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break; 10889 } 10890 break; 10891 10892 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break; 10893 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break; 10894 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break; 10895 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break; 10896 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break; 10897 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break; 10898 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break; 10899 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break; 10900 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break; 10901 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break; 10902 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break; 10903 10904 /* Events that aren't relevant at this point. */ 10905 case VMX_EXIT_EXT_INT: 10906 case VMX_EXIT_INT_WINDOW: 10907 case VMX_EXIT_NMI_WINDOW: 10908 case VMX_EXIT_TPR_BELOW_THRESHOLD: 10909 case VMX_EXIT_PREEMPT_TIMER: 10910 case VMX_EXIT_IO_INSTR: 10911 break; 10912 10913 /* Errors and unexpected events. */ 10914 case VMX_EXIT_INIT_SIGNAL: 10915 case VMX_EXIT_SIPI: 10916 case VMX_EXIT_IO_SMI: 10917 case VMX_EXIT_SMI: 10918 case VMX_EXIT_ERR_INVALID_GUEST_STATE: 10919 case VMX_EXIT_ERR_MSR_LOAD: 10920 case VMX_EXIT_ERR_MACHINE_CHECK: 10921 case VMX_EXIT_PML_FULL: 10922 case VMX_EXIT_VIRTUALIZED_EOI: 10923 break; 10924 10925 default: 10926 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason)); 10927 break; 10928 } 10929 #undef SET_BOTH 10930 #undef SET_EXIT 10931 10932 /* 10933 * Dtrace tracepoints go first. We do them here at once so we don't 10934 * have to copy the guest state saving and stuff a few dozen times. 10935 * Down side is that we've got to repeat the switch, though this time 10936 * we use enmEvent since the probes are a subset of what DBGF does. 10937 */ 10938 if (fDtrace1 || fDtrace2) 10939 { 10940 vmxHCReadExitQualVmcs(pVCpu, pVmxTransient); 10941 vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); 10942 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx; 10943 switch (enmEvent1) 10944 { 10945 /** @todo consider which extra parameters would be helpful for each probe. */ 10946 case DBGFEVENT_END: break; 10947 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break; 10948 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break; 10949 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break; 10950 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break; 10951 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break; 10952 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break; 10953 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break; 10954 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break; 10955 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break; 10956 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break; 10957 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break; 10958 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break; 10959 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break; 10960 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break; 10961 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break; 10962 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break; 10963 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break; 10964 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break; 10965 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break; 10966 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break; 10967 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break; 10968 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break; 10969 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break; 10970 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break; 10971 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break; 10972 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break; 10973 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break; 10974 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break; 10975 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break; 10976 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break; 10977 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break; 10978 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break; 10979 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx, 10980 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break; 10981 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break; 10982 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break; 10983 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break; 10984 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break; 10985 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break; 10986 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break; 10987 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break; 10988 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break; 10989 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break; 10990 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break; 10991 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break; 10992 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break; 10993 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break; 10994 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break; 10995 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break; 10996 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break; 10997 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break; 10998 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break; 10999 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break; 11000 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break; 11001 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break; 11002 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break; 11003 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break; 11004 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break; 11005 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break; 11006 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break; 11007 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break; 11008 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break; 11009 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break; 11010 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break; 11011 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break; 11012 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break; 11013 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break; 11014 } 11015 switch (enmEvent2) 11016 { 11017 /** @todo consider which extra parameters would be helpful for each probe. */ 11018 case DBGFEVENT_END: break; 11019 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break; 11020 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break; 11021 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break; 11022 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break; 11023 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break; 11024 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break; 11025 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break; 11026 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break; 11027 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break; 11028 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break; 11029 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break; 11030 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break; 11031 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break; 11032 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break; 11033 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx, 11034 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break; 11035 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break; 11036 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break; 11037 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break; 11038 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break; 11039 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break; 11040 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break; 11041 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break; 11042 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break; 11043 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break; 11044 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break; 11045 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break; 11046 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break; 11047 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break; 11048 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break; 11049 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break; 11050 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break; 11051 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break; 11052 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break; 11053 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break; 11054 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break; 11055 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break; 11056 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break; 11057 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break; 11058 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break; 11059 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break; 11060 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break; 11061 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break; 11062 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break; 11063 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break; 11064 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break; 11065 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break; 11066 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break; 11067 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break; 11068 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break; 11069 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break; 11070 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break; 11071 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break; 11072 } 11073 } 11074 11075 /* 11076 * Fire of the DBGF event, if enabled (our check here is just a quick one, 11077 * the DBGF call will do a full check). 11078 * 11079 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap. 11080 * Note! If we have to events, we prioritize the first, i.e. the instruction 11081 * one, in order to avoid event nesting. 11082 */ 11083 PVMCC pVM = pVCpu->CTX_SUFF(pVM); 11084 if ( enmEvent1 != DBGFEVENT_END 11085 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1)) 11086 { 11087 vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP); 11088 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg); 11089 if (rcStrict != VINF_SUCCESS) 11090 return rcStrict; 11091 } 11092 else if ( enmEvent2 != DBGFEVENT_END 11093 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2)) 11094 { 11095 vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP); 11096 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg); 11097 if (rcStrict != VINF_SUCCESS) 11098 return rcStrict; 11099 } 11100 11101 return VINF_SUCCESS; 11102 } 11103 11104 11105 /** 11106 * Single-stepping VM-exit filtering. 11107 * 11108 * This is preprocessing the VM-exits and deciding whether we've gotten far 11109 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit 11110 * handling is performed. 11111 * 11112 * @returns Strict VBox status code (i.e. informational status codes too). 11113 * @param pVCpu The cross context virtual CPU structure of the calling EMT. 11114 * @param pVmxTransient The VMX-transient structure. 11115 * @param pDbgState The debug state. 11116 */ 11117 DECLINLINE(VBOXSTRICTRC) vmxHCRunDebugHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState) 11118 { 11119 /* 11120 * Expensive (saves context) generic dtrace VM-exit probe. 11121 */ 11122 uint32_t const uExitReason = pVmxTransient->uExitReason; 11123 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED()) 11124 { /* more likely */ } 11125 else 11126 { 11127 vmxHCReadExitQualVmcs(pVCpu, pVmxTransient); 11128 int rc = vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); 11129 AssertRC(rc); 11130 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual); 11131 } 11132 11133 #ifndef IN_NEM_DARWIN 11134 /* 11135 * Check for host NMI, just to get that out of the way. 11136 */ 11137 if (uExitReason != VMX_EXIT_XCPT_OR_NMI) 11138 { /* normally likely */ } 11139 else 11140 { 11141 vmxHCReadExitIntInfoVmcs(pVCpu, pVmxTransient); 11142 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo); 11143 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI) 11144 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo); 11145 } 11146 #endif 11147 11148 /* 11149 * Check for single stepping event if we're stepping. 11150 */ 11151 if (VCPU_2_VMXSTATE(pVCpu).fSingleInstruction) 11152 { 11153 switch (uExitReason) 11154 { 11155 case VMX_EXIT_MTF: 11156 return vmxHCExitMtf(pVCpu, pVmxTransient); 11157 11158 /* Various events: */ 11159 case VMX_EXIT_XCPT_OR_NMI: 11160 case VMX_EXIT_EXT_INT: 11161 case VMX_EXIT_TRIPLE_FAULT: 11162 case VMX_EXIT_INT_WINDOW: 11163 case VMX_EXIT_NMI_WINDOW: 11164 case VMX_EXIT_TASK_SWITCH: 11165 case VMX_EXIT_TPR_BELOW_THRESHOLD: 11166 case VMX_EXIT_APIC_ACCESS: 11167 case VMX_EXIT_EPT_VIOLATION: 11168 case VMX_EXIT_EPT_MISCONFIG: 11169 case VMX_EXIT_PREEMPT_TIMER: 11170 11171 /* Instruction specific VM-exits: */ 11172 case VMX_EXIT_CPUID: 11173 case VMX_EXIT_GETSEC: 11174 case VMX_EXIT_HLT: 11175 case VMX_EXIT_INVD: 11176 case VMX_EXIT_INVLPG: 11177 case VMX_EXIT_RDPMC: 11178 case VMX_EXIT_RDTSC: 11179 case VMX_EXIT_RSM: 11180 case VMX_EXIT_VMCALL: 11181 case VMX_EXIT_VMCLEAR: 11182 case VMX_EXIT_VMLAUNCH: 11183 case VMX_EXIT_VMPTRLD: 11184 case VMX_EXIT_VMPTRST: 11185 case VMX_EXIT_VMREAD: 11186 case VMX_EXIT_VMRESUME: 11187 case VMX_EXIT_VMWRITE: 11188 case VMX_EXIT_VMXOFF: 11189 case VMX_EXIT_VMXON: 11190 case VMX_EXIT_MOV_CRX: 11191 case VMX_EXIT_MOV_DRX: 11192 case VMX_EXIT_IO_INSTR: 11193 case VMX_EXIT_RDMSR: 11194 case VMX_EXIT_WRMSR: 11195 case VMX_EXIT_MWAIT: 11196 case VMX_EXIT_MONITOR: 11197 case VMX_EXIT_PAUSE: 11198 case VMX_EXIT_GDTR_IDTR_ACCESS: 11199 case VMX_EXIT_LDTR_TR_ACCESS: 11200 case VMX_EXIT_INVEPT: 11201 case VMX_EXIT_RDTSCP: 11202 case VMX_EXIT_INVVPID: 11203 case VMX_EXIT_WBINVD: 11204 case VMX_EXIT_XSETBV: 11205 case VMX_EXIT_RDRAND: 11206 case VMX_EXIT_INVPCID: 11207 case VMX_EXIT_VMFUNC: 11208 case VMX_EXIT_RDSEED: 11209 case VMX_EXIT_XSAVES: 11210 case VMX_EXIT_XRSTORS: 11211 { 11212 int rc = vmxHCImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP); 11213 AssertRCReturn(rc, rc); 11214 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart 11215 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart) 11216 return VINF_EM_DBG_STEPPED; 11217 break; 11218 } 11219 11220 /* Errors and unexpected events: */ 11221 case VMX_EXIT_INIT_SIGNAL: 11222 case VMX_EXIT_SIPI: 11223 case VMX_EXIT_IO_SMI: 11224 case VMX_EXIT_SMI: 11225 case VMX_EXIT_ERR_INVALID_GUEST_STATE: 11226 case VMX_EXIT_ERR_MSR_LOAD: 11227 case VMX_EXIT_ERR_MACHINE_CHECK: 11228 case VMX_EXIT_PML_FULL: 11229 case VMX_EXIT_VIRTUALIZED_EOI: 11230 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */ 11231 break; 11232 11233 default: 11234 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason)); 11235 break; 11236 } 11237 } 11238 11239 /* 11240 * Check for debugger event breakpoints and dtrace probes. 11241 */ 11242 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U 11243 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) ) 11244 { 11245 VBOXSTRICTRC rcStrict = vmxHCHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason); 11246 if (rcStrict != VINF_SUCCESS) 11247 return rcStrict; 11248 } 11249 11250 /* 11251 * Normal processing. 11252 */ 11253 #ifdef HMVMX_USE_FUNCTION_TABLE 11254 return g_aVMExitHandlers[uExitReason].pfn(pVCpu, pVmxTransient); 11255 #else 11256 return vmxHCHandleExit(pVCpu, pVmxTransient, uExitReason); 11257 #endif 11258 } 11259 11260 /** @} */
Note:
See TracChangeset
for help on using the changeset viewer.