Changeset 48296 in vbox
- Timestamp:
- Sep 5, 2013 9:52:17 AM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMR0.cpp
r48280 r48296 187 187 * @param rc The status code. 188 188 */ 189 static void 189 static void hmR0FirstRcSetStatus(PHMR0FIRSTRC pFirstRc, int rc) 190 190 { 191 191 if ( RT_FAILURE(rc) … … 386 386 if (RT_SUCCESS(g_HvmR0.lLastError)) 387 387 { 388 /* Reread in case we've changed it. */388 /* Reread in case it was changed by hmR0InitIntelCpu(). */ 389 389 g_HvmR0.vmx.Msrs.u64FeatureCtrl = ASMRdMsr(MSR_IA32_FEATURE_CONTROL); 390 390 391 /** @todo r=ramshankar: This should be fixed for when the host is in SMX mode. 392 * Probably don't need to recheck it here. It's done in 393 * hmR0InitIntelCpu(). */ 394 if ( (g_HvmR0.vmx.Msrs.u64FeatureCtrl & (MSR_IA32_FEATURE_CONTROL_VMXON | MSR_IA32_FEATURE_CONTROL_LOCK)) 395 == (MSR_IA32_FEATURE_CONTROL_VMXON | MSR_IA32_FEATURE_CONTROL_LOCK)) 391 /* 392 * Read all relevant registers and MSRs. 393 */ 394 g_HvmR0.vmx.u64HostCr4 = ASMGetCR4(); 395 g_HvmR0.vmx.u64HostEfer = ASMRdMsr(MSR_K6_EFER); 396 g_HvmR0.vmx.Msrs.u64BasicInfo = ASMRdMsr(MSR_IA32_VMX_BASIC_INFO); 397 g_HvmR0.vmx.Msrs.VmxPinCtls.u = ASMRdMsr(MSR_IA32_VMX_PINBASED_CTLS); 398 g_HvmR0.vmx.Msrs.VmxProcCtls.u = ASMRdMsr(MSR_IA32_VMX_PROCBASED_CTLS); 399 g_HvmR0.vmx.Msrs.VmxExit.u = ASMRdMsr(MSR_IA32_VMX_EXIT_CTLS); 400 g_HvmR0.vmx.Msrs.VmxEntry.u = ASMRdMsr(MSR_IA32_VMX_ENTRY_CTLS); 401 g_HvmR0.vmx.Msrs.u64Misc = ASMRdMsr(MSR_IA32_VMX_MISC); 402 g_HvmR0.vmx.Msrs.u64Cr0Fixed0 = ASMRdMsr(MSR_IA32_VMX_CR0_FIXED0); 403 g_HvmR0.vmx.Msrs.u64Cr0Fixed1 = ASMRdMsr(MSR_IA32_VMX_CR0_FIXED1); 404 g_HvmR0.vmx.Msrs.u64Cr4Fixed0 = ASMRdMsr(MSR_IA32_VMX_CR4_FIXED0); 405 g_HvmR0.vmx.Msrs.u64Cr4Fixed1 = ASMRdMsr(MSR_IA32_VMX_CR4_FIXED1); 406 g_HvmR0.vmx.Msrs.u64VmcsEnum = ASMRdMsr(MSR_IA32_VMX_VMCS_ENUM); 407 /* VPID 16 bits ASID. */ 408 g_HvmR0.uMaxAsid = 0x10000; /* exclusive */ 409 410 if (g_HvmR0.vmx.Msrs.VmxProcCtls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL) 411 { 412 g_HvmR0.vmx.Msrs.VmxProcCtls2.u = ASMRdMsr(MSR_IA32_VMX_PROCBASED_CTLS2); 413 if (g_HvmR0.vmx.Msrs.VmxProcCtls2.n.allowed1 & (VMX_VMCS_CTRL_PROC_EXEC2_EPT | VMX_VMCS_CTRL_PROC_EXEC2_VPID)) 414 g_HvmR0.vmx.Msrs.u64EptVpidCaps = ASMRdMsr(MSR_IA32_VMX_EPT_VPID_CAP); 415 416 if (g_HvmR0.vmx.Msrs.VmxProcCtls2.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC2_VMFUNC) 417 g_HvmR0.vmx.Msrs.u64Vmfunc = ASMRdMsr(MSR_IA32_VMX_VMFUNC); 418 } 419 420 if (!g_HvmR0.vmx.fUsingSUPR0EnableVTx) 396 421 { 397 422 /* 398 * Read all relevant registers and MSRs.423 * Enter root mode 399 424 */ 400 g_HvmR0.vmx.u64HostCr4 = ASMGetCR4(); 401 g_HvmR0.vmx.u64HostEfer = ASMRdMsr(MSR_K6_EFER); 402 g_HvmR0.vmx.Msrs.u64BasicInfo = ASMRdMsr(MSR_IA32_VMX_BASIC_INFO); 403 g_HvmR0.vmx.Msrs.VmxPinCtls.u = ASMRdMsr(MSR_IA32_VMX_PINBASED_CTLS); 404 g_HvmR0.vmx.Msrs.VmxProcCtls.u = ASMRdMsr(MSR_IA32_VMX_PROCBASED_CTLS); 405 g_HvmR0.vmx.Msrs.VmxExit.u = ASMRdMsr(MSR_IA32_VMX_EXIT_CTLS); 406 g_HvmR0.vmx.Msrs.VmxEntry.u = ASMRdMsr(MSR_IA32_VMX_ENTRY_CTLS); 407 g_HvmR0.vmx.Msrs.u64Misc = ASMRdMsr(MSR_IA32_VMX_MISC); 408 g_HvmR0.vmx.Msrs.u64Cr0Fixed0 = ASMRdMsr(MSR_IA32_VMX_CR0_FIXED0); 409 g_HvmR0.vmx.Msrs.u64Cr0Fixed1 = ASMRdMsr(MSR_IA32_VMX_CR0_FIXED1); 410 g_HvmR0.vmx.Msrs.u64Cr4Fixed0 = ASMRdMsr(MSR_IA32_VMX_CR4_FIXED0); 411 g_HvmR0.vmx.Msrs.u64Cr4Fixed1 = ASMRdMsr(MSR_IA32_VMX_CR4_FIXED1); 412 g_HvmR0.vmx.Msrs.u64VmcsEnum = ASMRdMsr(MSR_IA32_VMX_VMCS_ENUM); 413 /* VPID 16 bits ASID. */ 414 g_HvmR0.uMaxAsid = 0x10000; /* exclusive */ 415 416 if (g_HvmR0.vmx.Msrs.VmxProcCtls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL) 425 RTR0MEMOBJ hScatchMemObj; 426 rc = RTR0MemObjAllocCont(&hScatchMemObj, PAGE_SIZE, false /* fExecutable */); 427 if (RT_FAILURE(rc)) 417 428 { 418 g_HvmR0.vmx.Msrs.VmxProcCtls2.u = ASMRdMsr(MSR_IA32_VMX_PROCBASED_CTLS2); 419 if (g_HvmR0.vmx.Msrs.VmxProcCtls2.n.allowed1 & (VMX_VMCS_CTRL_PROC_EXEC2_EPT | VMX_VMCS_CTRL_PROC_EXEC2_VPID)) 420 g_HvmR0.vmx.Msrs.u64EptVpidCaps = ASMRdMsr(MSR_IA32_VMX_EPT_VPID_CAP); 421 422 if (g_HvmR0.vmx.Msrs.VmxProcCtls2.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC2_VMFUNC) 423 g_HvmR0.vmx.Msrs.u64Vmfunc = ASMRdMsr(MSR_IA32_VMX_VMFUNC); 429 LogRel(("hmR0InitIntel: RTR0MemObjAllocCont(,PAGE_SIZE,true) -> %Rrc\n", rc)); 430 return rc; 424 431 } 425 432 426 if (!g_HvmR0.vmx.fUsingSUPR0EnableVTx) 433 void *pvScatchPage = RTR0MemObjAddress(hScatchMemObj); 434 RTHCPHYS HCPhysScratchPage = RTR0MemObjGetPagePhysAddr(hScatchMemObj, 0); 435 ASMMemZeroPage(pvScatchPage); 436 437 /* Set revision dword at the beginning of the structure. */ 438 *(uint32_t *)pvScatchPage = MSR_IA32_VMX_BASIC_INFO_VMCS_ID(g_HvmR0.vmx.Msrs.u64BasicInfo); 439 440 /* Make sure we don't get rescheduled to another cpu during this probe. */ 441 RTCCUINTREG fFlags = ASMIntDisableFlags(); 442 443 /* 444 * Check CR4.VMXE 445 */ 446 g_HvmR0.vmx.u64HostCr4 = ASMGetCR4(); 447 if (!(g_HvmR0.vmx.u64HostCr4 & X86_CR4_VMXE)) 448 { 449 /* In theory this bit could be cleared behind our back. Which would cause 450 #UD faults when we try to execute the VMX instructions... */ 451 ASMSetCR4(g_HvmR0.vmx.u64HostCr4 | X86_CR4_VMXE); 452 } 453 454 /* 455 * The only way of checking if we're in VMX root mode or not is to try and enter it. 456 * There is no instruction or control bit that tells us if we're in VMX root mode. 457 * Therefore, try and enter VMX root mode here. 458 */ 459 rc = VMXEnable(HCPhysScratchPage); 460 if (RT_SUCCESS(rc)) 461 { 462 g_HvmR0.vmx.fSupported = true; 463 VMXDisable(); 464 } 465 else 427 466 { 428 467 /* 429 * Enter root mode 468 * KVM leaves the CPU in VMX root mode. Not only is this not allowed, 469 * it will crash the host when we enter raw mode, because: 470 * 471 * (a) clearing X86_CR4_VMXE in CR4 causes a #GP (we no longer modify 472 * this bit), and 473 * (b) turning off paging causes a #GP (unavoidable when switching 474 * from long to 32 bits mode or 32 bits to PAE). 475 * 476 * They should fix their code, but until they do we simply refuse to run. 430 477 */ 431 RTR0MEMOBJ hScatchMemObj; 432 rc = RTR0MemObjAllocCont(&hScatchMemObj, PAGE_SIZE, false /* fExecutable */); 433 if (RT_FAILURE(rc)) 434 { 435 LogRel(("hmR0InitIntel: RTR0MemObjAllocCont(,PAGE_SIZE,true) -> %Rrc\n", rc)); 436 return rc; 437 } 438 439 void *pvScatchPage = RTR0MemObjAddress(hScatchMemObj); 440 RTHCPHYS HCPhysScratchPage = RTR0MemObjGetPagePhysAddr(hScatchMemObj, 0); 441 ASMMemZeroPage(pvScatchPage); 442 443 /* Set revision dword at the beginning of the structure. */ 444 *(uint32_t *)pvScatchPage = MSR_IA32_VMX_BASIC_INFO_VMCS_ID(g_HvmR0.vmx.Msrs.u64BasicInfo); 445 446 /* Make sure we don't get rescheduled to another cpu during this probe. */ 447 RTCCUINTREG fFlags = ASMIntDisableFlags(); 448 449 /* 450 * Check CR4.VMXE 451 */ 452 g_HvmR0.vmx.u64HostCr4 = ASMGetCR4(); 453 if (!(g_HvmR0.vmx.u64HostCr4 & X86_CR4_VMXE)) 454 { 455 /* In theory this bit could be cleared behind our back. Which would cause 456 #UD faults when we try to execute the VMX instructions... */ 457 ASMSetCR4(g_HvmR0.vmx.u64HostCr4 | X86_CR4_VMXE); 458 } 459 460 /* 461 * The only way of checking if we're in VMX root mode or not is to try and enter it. 462 * There is no instruction or control bit that tells us if we're in VMX root mode. 463 * Therefore, try and enter VMX root mode here. 464 */ 465 rc = VMXEnable(HCPhysScratchPage); 466 if (RT_SUCCESS(rc)) 467 { 468 g_HvmR0.vmx.fSupported = true; 469 VMXDisable(); 470 } 471 else 472 { 473 /* 474 * KVM leaves the CPU in VMX root mode. Not only is this not allowed, 475 * it will crash the host when we enter raw mode, because: 476 * 477 * (a) clearing X86_CR4_VMXE in CR4 causes a #GP (we no longer modify 478 * this bit), and 479 * (b) turning off paging causes a #GP (unavoidable when switching 480 * from long to 32 bits mode or 32 bits to PAE). 481 * 482 * They should fix their code, but until they do we simply refuse to run. 483 */ 484 g_HvmR0.lLastError = VERR_VMX_IN_VMX_ROOT_MODE; 485 } 486 487 /* Restore CR4 again; don't leave the X86_CR4_VMXE flag set 488 if it wasn't so before (some software could incorrectly 489 think it's in VMX mode). */ 490 ASMSetCR4(g_HvmR0.vmx.u64HostCr4); 491 ASMSetFlags(fFlags); 492 493 RTR0MemObjFree(hScatchMemObj, false); 478 g_HvmR0.lLastError = VERR_VMX_IN_VMX_ROOT_MODE; 479 Assert(g_HvmR0.vmx.fSupported == false); 494 480 } 495 } 496 else 497 { 498 AssertFailed(); /* can't hit this case anymore */ 499 g_HvmR0.lLastError = VERR_VMX_ILLEGAL_FEATURE_CONTROL_MSR; 481 482 /* Restore CR4 again; don't leave the X86_CR4_VMXE flag set 483 if it wasn't so before (some software could incorrectly 484 think it's in VMX mode). */ 485 ASMSetCR4(g_HvmR0.vmx.u64HostCr4); 486 ASMSetFlags(fFlags); 487 488 RTR0MemObjFree(hScatchMemObj, false); 500 489 } 501 490 502 491 if (g_HvmR0.vmx.fSupported) 503 492 { 504 /* Call the global VT-x initialization routine. */505 493 rc = VMXR0GlobalInit(); 506 494 if (RT_FAILURE(rc))
Note:
See TracChangeset
for help on using the changeset viewer.