- Timestamp:
- Mar 9, 2010 8:16:59 PM (15 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/EM.cpp
r26260 r27231 522 522 rc = SSMR3PutU32(pSSM, pVCpu->em.s.enmPrevState); 523 523 AssertRCReturn(rc, rc); 524 525 /* Save mwait state. */ 526 rc = SSMR3PutU32(pSSM, pVCpu->em.s.mwait.fWait); 527 AssertRCReturn(rc, rc); 528 rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.mwait.uMWaitEAX); 529 AssertRCReturn(rc, rc); 530 rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.mwait.uMWaitECX); 531 AssertRCReturn(rc, rc); 532 rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.mwait.uMonitorEAX); 533 AssertRCReturn(rc, rc); 534 rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.mwait.uMonitorECX); 535 AssertRCReturn(rc, rc); 536 rc = SSMR3PutGCPtr(pSSM, pVCpu->em.s.mwait.uMonitorEDX); 537 AssertRCReturn(rc, rc); 524 538 } 525 539 return VINF_SUCCESS; … … 542 556 */ 543 557 if ( uVersion != EM_SAVED_STATE_VERSION 558 && uVersion != EM_SAVED_STATE_VERSION_PRE_MWAIT 544 559 && uVersion != EM_SAVED_STATE_VERSION_PRE_SMP) 545 560 { … … 570 585 pVCpu->em.s.enmState = EMSTATE_SUSPENDED; 571 586 } 587 if (uVersion > EM_SAVED_STATE_VERSION_PRE_MWAIT) 588 { 589 /* Load mwait state. */ 590 rc = SSMR3GetU32(pSSM, &pVCpu->em.s.mwait.fWait); 591 AssertRCReturn(rc, rc); 592 rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.mwait.uMWaitEAX); 593 AssertRCReturn(rc, rc); 594 rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.mwait.uMWaitECX); 595 AssertRCReturn(rc, rc); 596 rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.mwait.uMonitorEAX); 597 AssertRCReturn(rc, rc); 598 rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.mwait.uMonitorECX); 599 AssertRCReturn(rc, rc); 600 rc = SSMR3GetGCPtr(pSSM, &pVCpu->em.s.mwait.uMonitorEDX); 601 AssertRCReturn(rc, rc); 602 } 603 572 604 Assert(!pVCpu->em.s.pCliStatTree); 573 605 } … … 1969 2001 { 1970 2002 STAM_REL_PROFILE_START(&pVCpu->em.s.StatHalted, y); 1971 rc = VMR3WaitHalted(pVM, pVCpu, !(CPUMGetGuestEFlags(pVCpu) & X86_EFL_IF)); 2003 if (pVCpu->em.s.mwait.fWait & EMMWAIT_FLAG_ACTIVE) 2004 { 2005 /* mwait has a special extension where it's woken up when an interrupt is pending even when IF=0. */ 2006 rc = VMR3WaitHalted(pVM, pVCpu, !(pVCpu->em.s.mwait.fWait & EMMWAIT_FLAG_BREAKIRQIF0) && !(CPUMGetGuestEFlags(pVCpu) & X86_EFL_IF)); 2007 pVCpu->em.s.mwait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0); 2008 } 2009 else 2010 rc = VMR3WaitHalted(pVM, pVCpu, !(CPUMGetGuestEFlags(pVCpu) & X86_EFL_IF)); 2011 1972 2012 STAM_REL_PROFILE_STOP(&pVCpu->em.s.StatHalted, y); 1973 2013 break; -
trunk/src/VBox/VMM/EMInternal.h
r26260 r27231 43 43 44 44 /** The saved state version. */ 45 #define EM_SAVED_STATE_VERSION 3 45 #define EM_SAVED_STATE_VERSION 4 46 #define EM_SAVED_STATE_VERSION_PRE_MWAIT 3 46 47 #define EM_SAVED_STATE_VERSION_PRE_SMP 2 48 49 50 /** 51 * MWait state flags. 52 */ 53 /* MWait activated. */ 54 #define EMMWAIT_FLAG_ACTIVE RT_BIT(0) 55 /* MWait will continue when an interrupt is pending even when IF=0. */ 56 #define EMMWAIT_FLAG_BREAKIRQIF0 RT_BIT(1) 57 /* Monitor instruction was executed previously. */ 58 #define EMMWAIT_FLAG_MONITOR_ACTIVE RT_BIT(2) 59 47 60 48 61 /** … … 336 349 #endif 337 350 351 /* MWait halt state. */ 352 struct 353 { 354 uint32_t fWait; /* type of mwait; see EMMWAIT_FLAG_* */ 355 uint32_t a32Padding[1]; 356 RTGCPTR uMWaitEAX; /* mwait hints */ 357 RTGCPTR uMWaitECX; /* mwait extensions */ 358 RTGCPTR uMonitorEAX; /* monitored address. */ 359 RTGCPTR uMonitorECX; /* monitor extension. */ 360 RTGCPTR uMonitorEDX; /* monitor hint. */ 361 } mwait; 362 338 363 union 339 364 { -
trunk/src/VBox/VMM/HWACCMInternal.h
r27167 r27231 818 818 STAMCOUNTER StatExitHlt; 819 819 STAMCOUNTER StatExitMwait; 820 STAMCOUNTER StatExitMonitor; 820 821 STAMCOUNTER StatExitLMSW; 821 822 STAMCOUNTER StatExitIOWrite; -
trunk/src/VBox/VMM/VMMAll/EMAll.cpp
r27129 r27231 2718 2718 * MONITOR Emulation. 2719 2719 */ 2720 static int emInterpretMonitor(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize)2720 VMMDECL(int) EMInterpretMonitor(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame) 2721 2721 { 2722 2722 uint32_t u32Dummy, u32ExtFeatures, cpl; 2723 2723 2724 Assert(pDis->mode != CPUMODE_64BIT); /** @todo check */2725 2724 if (pRegFrame->ecx != 0) 2725 { 2726 Log(("emInterpretMonitor: unexpected ecx=%x -> recompiler!!\n", pRegFrame->ecx)); 2726 2727 return VERR_EM_INTERPRETER; /* illegal value. */ 2728 } 2727 2729 2728 2730 /* Get the current privilege level. */ … … 2735 2737 return VERR_EM_INTERPRETER; /* not supported */ 2736 2738 2739 pVCpu->em.s.mwait.uMonitorEAX = pRegFrame->rax; 2740 pVCpu->em.s.mwait.uMonitorECX = pRegFrame->rcx; 2741 pVCpu->em.s.mwait.uMonitorEDX = pRegFrame->rdx; 2742 pVCpu->em.s.mwait.fWait |= EMMWAIT_FLAG_MONITOR_ACTIVE; 2737 2743 return VINF_SUCCESS; 2738 2744 } 2739 2745 2746 static int emInterpretMonitor(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize) 2747 { 2748 return EMInterpretMonitor(pVM, pVCpu, pRegFrame); 2749 } 2750 2740 2751 2741 2752 /** … … 2744 2755 VMMDECL(int) EMInterpretMWait(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame) 2745 2756 { 2746 uint32_t u32Dummy, u32ExtFeatures, cpl; 2747 2748 /* @todo bit 1 is supposed to tell the cpu to wake us up on interrupts even if IF is cleared. 2749 * Not sure which models. Intel docs say ecx and eax must be zero for Pentium 4 CPUs 2750 * CPUID.05H.ECX[0] defines support for power management extensions (eax) 2751 */ 2752 if (pRegFrame->ecx != 0) 2753 return VERR_EM_INTERPRETER; /* illegal value. */ 2757 uint32_t u32Dummy, u32ExtFeatures, cpl, u32MWaitFeatures; 2754 2758 2755 2759 /* Get the current privilege level. */ … … 2762 2766 return VERR_EM_INTERPRETER; /* not supported */ 2763 2767 2768 /* 2769 * CPUID.05H.ECX[0] defines support for power management extensions (eax) 2770 * CPUID.05H.ECX[1] defines support for interrupts as break events for mwait even when IF=0 2771 */ 2772 CPUMGetGuestCpuId(pVCpu, 5, &u32Dummy, &u32Dummy, &u32MWaitFeatures, &u32Dummy); 2773 if (pRegFrame->ecx > 1) 2774 { 2775 Log(("EMInterpretMWait: unexpected ecx value %x -> recompiler\n", pRegFrame->ecx)); 2776 return VERR_EM_INTERPRETER; /* illegal value. */ 2777 } 2778 2779 if (pRegFrame->ecx) 2780 { 2781 if (!(u32MWaitFeatures & X86_CPUID_MWAIT_ECX_BREAKIRQIF0)) 2782 { 2783 Log(("EMInterpretMWait: unsupported X86_CPUID_MWAIT_ECX_BREAKIRQIF0 -> recompiler\n")); 2784 return VERR_EM_INTERPRETER; /* illegal value. */ 2785 } 2786 2787 pVCpu->em.s.mwait.fWait = EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0; 2788 } 2789 else 2790 pVCpu->em.s.mwait.fWait = EMMWAIT_FLAG_ACTIVE; 2791 2792 pVCpu->em.s.mwait.uMWaitEAX = pRegFrame->rax; 2793 pVCpu->em.s.mwait.uMWaitECX = pRegFrame->rcx; 2794 2764 2795 /** @todo not completely correct */ 2765 2796 return VINF_EM_HALT; … … 2768 2799 static int emInterpretMWait(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbSize) 2769 2800 { 2770 Assert(pDis->mode != CPUMODE_64BIT); /** @todo check */2771 2772 2801 return EMInterpretMWait(pVM, pVCpu, pRegFrame); 2773 2802 } … … 3500 3529 } 3501 3530 3531 /** 3532 * Determine if we should continue after encountering a hlt or mwait instruction 3533 * 3534 * @returns boolean 3535 * @param pVCpu The VMCPU to operate on. 3536 * @param pCtx Current CPU context 3537 */ 3538 VMMDECL(bool) EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx) 3539 { 3540 if ( pCtx->eflags.Bits.u1IF 3541 || ((pVCpu->em.s.mwait.fWait & (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0)) == (EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0))) 3542 { 3543 pVCpu->em.s.mwait.fWait &= ~(EMMWAIT_FLAG_ACTIVE | EMMWAIT_FLAG_BREAKIRQIF0); 3544 return !!VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC)); 3545 } 3546 3547 return false; 3548 } 3549 -
trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp
r26152 r27231 344 344 | SVM_CTRL2_INTERCEPT_SKINIT 345 345 | SVM_CTRL2_INTERCEPT_WBINVD 346 | SVM_CTRL2_INTERCEPT_MONITOR 346 347 | SVM_CTRL2_INTERCEPT_MWAIT_UNCOND; /* don't execute mwait or else we'll idle inside the guest (host thinks the cpu load is high) */ 347 348 ; … … 2349 2350 STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatExitHlt); 2350 2351 pCtx->rip++; /* skip hlt */ 2351 if ( pCtx->eflags.Bits.u1IF 2352 && VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC))) 2352 if (EMShouldContinueAfterHalt(pVCpu, pCtx)) 2353 2353 goto ResumeExecution; 2354 2354 … … 2369 2369 if ( rc == VINF_SUCCESS 2370 2370 || ( rc == VINF_EM_HALT 2371 && pCtx->eflags.Bits.u1IF 2372 && VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC))) 2371 && EMShouldContinueAfterHalt(pVCpu, pCtx)) 2373 2372 ) 2374 2373 goto ResumeExecution; … … 2376 2375 AssertMsg(rc == VERR_EM_INTERPRETER || rc == VINF_EM_HALT, ("EMU: mwait failed with %Rrc\n", rc)); 2377 2376 break; 2377 2378 case SVM_EXIT_MONITOR: 2379 { 2380 Log2(("SVM: monitor\n")); 2381 2382 STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatExitMonitor); 2383 rc = EMInterpretMonitor(pVM, pVCpu, CPUMCTX2CORE(pCtx)); 2384 if (rc == VINF_SUCCESS) 2385 { 2386 /* Update EIP and continue execution. */ 2387 pCtx->rip += 3; /* Note: hardcoded opcode size assumption! */ 2388 goto ResumeExecution; 2389 } 2390 AssertMsg(rc == VERR_EM_INTERPRETER, ("EMU: monitor failed with %Rrc\n", rc)); 2391 break; 2392 } 2393 2378 2394 2379 2395 case SVM_EXIT_VMMCALL: … … 2482 2498 break; 2483 2499 2484 case SVM_EXIT_MONITOR:2485 2500 case SVM_EXIT_PAUSE: 2486 2501 case SVM_EXIT_MWAIT_ARMED: -
trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp
r26296 r27231 413 413 | VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_UNCOND_IO_EXIT 414 414 | VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDPMC_EXIT 415 | VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MONITOR_EXIT 415 416 | VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MWAIT_EXIT; /* don't execute mwait or else we'll idle inside the guest (host thinks the cpu load is high) */ 416 417 … … 3530 3531 } 3531 3532 3533 case VMX_EXIT_MONITOR: /* 39 Guest software attempted to execute MONITOR. */ 3534 { 3535 Log2(("VMX: monitor\n")); 3536 3537 STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatExitMonitor); 3538 rc = EMInterpretMonitor(pVM, pVCpu, CPUMCTX2CORE(pCtx)); 3539 if (rc == VINF_SUCCESS) 3540 { 3541 /* Update EIP and continue execution. */ 3542 pCtx->rip += cbInstr; 3543 goto ResumeExecution; 3544 } 3545 AssertMsg(rc == VERR_EM_INTERPRETER, ("EMU: monitor failed with %Rrc\n", rc)); 3546 break; 3547 } 3548 3532 3549 case VMX_EXIT_WRMSR: /* 32 WRMSR. Guest software attempted to execute WRMSR. */ 3533 3550 /* When an interrupt is pending, we'll let MSR_K8_LSTAR writes fault in our TPR patch code. */ … … 3975 3992 STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatExitHlt); 3976 3993 pCtx->rip++; /* skip hlt */ 3977 if ( pCtx->eflags.Bits.u1IF 3978 && VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC))) 3994 if (EMShouldContinueAfterHalt(pVCpu, pCtx)) 3979 3995 goto ResumeExecution; 3980 3996 … … 3995 4011 if ( rc == VINF_SUCCESS 3996 4012 || ( rc == VINF_EM_HALT 3997 && pCtx->eflags.Bits.u1IF 3998 && VMCPU_FF_ISPENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC|VMCPU_FF_INTERRUPT_PIC))) 4013 && EMShouldContinueAfterHalt(pVCpu, pCtx)) 3999 4014 ) 4000 4015 goto ResumeExecution; … … 4047 4062 case VMX_EXIT_RDMSR: /* 31 RDMSR. Guest software attempted to execute RDMSR. */ 4048 4063 case VMX_EXIT_WRMSR: /* 32 WRMSR. Guest software attempted to execute WRMSR. */ 4064 case VMX_EXIT_PAUSE: /* 40 Guest software attempted to execute PAUSE. */ 4049 4065 case VMX_EXIT_MONITOR: /* 39 Guest software attempted to execute MONITOR. */ 4050 case VMX_EXIT_PAUSE: /* 40 Guest software attempted to execute PAUSE. */4051 4066 /* Note: If we decide to emulate them here, then we must sync the MSRs that could have been changed (sysenter, fs/gs base)!!! */ 4052 4067 rc = VERR_EM_INTERPRETER;
Note:
See TracChangeset
for help on using the changeset viewer.