Changeset 87535 in vbox for trunk/src/VBox/VMM/VMMR0
- Timestamp:
- Feb 2, 2021 2:02:11 PM (4 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HMR0.cpp
r87532 r87535 51 51 static DECLCALLBACK(void) hmR0EnableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2); 52 52 static DECLCALLBACK(void) hmR0DisableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2); 53 static DECLCALLBACK(void) hmR0InitIntelCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2);54 static DECLCALLBACK(void) hmR0InitAmdCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2);55 53 static DECLCALLBACK(void) hmR0PowerCallback(RTPOWEREVENT enmEvent, void *pvUser); 56 54 static DECLCALLBACK(void) hmR0MpEventCallback(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvData); … … 73 71 typedef HMR0FIRSTRC *PHMR0FIRSTRC; 74 72 75 76 /********************************************************************************************************************************* 77 * Global Variables * 78 *********************************************************************************************************************************/ 79 /** 80 * Global data. 81 */ 82 static struct 83 { 84 /** Per CPU globals. */ 85 HMPHYSCPU aCpuInfo[RTCPUSET_MAX_CPUS]; 86 87 /** @name Ring-0 method table for AMD-V and VT-x specific operations. 88 * @{ */ 73 /** 74 * Ring-0 method table for AMD-V and VT-x specific operations. 75 */ 76 typedef struct HMR0VTABLE 77 { 89 78 DECLR0CALLBACKMEMBER(int, pfnEnterSession, (PVMCPUCC pVCpu)); 90 79 DECLR0CALLBACKMEMBER(void, pfnThreadCtxCallback, (RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)); … … 98 87 DECLR0CALLBACKMEMBER(int, pfnTermVM, (PVMCC pVM)); 99 88 DECLR0CALLBACKMEMBER(int, pfnSetupVM, (PVMCC pVM)); 100 /** @} */ 89 } HMR0VTABLE; 90 91 92 /********************************************************************************************************************************* 93 * Global Variables * 94 *********************************************************************************************************************************/ 95 /** The active ring-0 HM operations (copied from one of the table at init). */ 96 static HMR0VTABLE g_HmR0Ops; 97 98 /** Set if VT-x (VMX) is supported by the CPU. */ 99 bool g_fHmVmxSupported = false; 100 /** Set if AMD-V is supported by the CPU. */ 101 bool g_fHmSvmSupported = false; 102 /** Maximum allowed ASID/VPID (inclusive). 103 * @todo r=bird: This is exclusive for VT-x according to source code comment. 104 * Couldn't immediately find any docs on AMD-V, but suspect it is 105 * exclusive there as well given how hmR0SvmFlushTaggedTlb() use it. */ 106 uint32_t g_uHmMaxAsid; 107 108 109 /** 110 * Global data. 111 */ 112 static struct 113 { 114 /** Per CPU globals. */ 115 HMPHYSCPU aCpuInfo[RTCPUSET_MAX_CPUS]; 101 116 102 117 /** Hardware-virtualization data. */ … … 160 175 161 176 162 /** Set if VT-x (VMX) is supported by the CPU. */ 163 bool g_fHmVmxSupported = false; 164 /** Set if AMD-V is supported by the CPU. */ 165 bool g_fHmSvmSupported = false; 166 /** Maximum allowed ASID/VPID (inclusive). 167 * @todo r=bird: This is exclusive for VT-x according to source code comment. 168 * Couldn't immediately find any docs on AMD-V, but suspect it is 169 * exclusive there as well given how hmR0SvmFlushTaggedTlb() use it. */ 170 uint32_t g_uHmMaxAsid; 177 /** HM ring-0 operations for VT-x. */ 178 static HMR0VTABLE const g_HmR0OpsVmx = 179 { 180 /* .pfnEnterSession = */ VMXR0Enter, 181 /* .pfnThreadCtxCallback = */ VMXR0ThreadCtxCallback, 182 /* .pfnCallRing3Callback = */ VMXR0CallRing3Callback, 183 /* .pfnExportHostState = */ VMXR0ExportHostState, 184 /* .pfnRunGuestCode = */ VMXR0RunGuestCode, 185 /* .pfnEnableCpu = */ VMXR0EnableCpu, 186 /* .pfnDisableCpu = */ VMXR0DisableCpu, 187 /* .pfnInitVM = */ VMXR0InitVM, 188 /* .pfnTermVM = */ VMXR0TermVM, 189 /* .pfnSetupVM = */ VMXR0SetupVM, 190 }; 191 192 /** HM ring-0 operations for AMD-V. */ 193 static HMR0VTABLE const g_HmR0OpsSvm = 194 { 195 /* .pfnEnterSession = */ SVMR0Enter, 196 /* .pfnThreadCtxCallback = */ SVMR0ThreadCtxCallback, 197 /* .pfnCallRing3Callback = */ SVMR0CallRing3Callback, 198 /* .pfnExportHostState = */ SVMR0ExportHostState, 199 /* .pfnRunGuestCode = */ SVMR0RunGuestCode, 200 /* .pfnEnableCpu = */ SVMR0EnableCpu, 201 /* .pfnDisableCpu = */ SVMR0DisableCpu, 202 /* .pfnInitVM = */ SVMR0InitVM, 203 /* .pfnTermVM = */ SVMR0TermVM, 204 /* .pfnSetupVM = */ SVMR0SetupVM, 205 }; 206 207 208 /** @name Dummy callback handlers for when neither VT-x nor AMD-V is supported. 209 * @{ */ 210 211 static DECLCALLBACK(int) hmR0DummyEnter(PVMCPUCC pVCpu) 212 { 213 RT_NOREF(pVCpu); 214 return VINF_SUCCESS; 215 } 216 217 static DECLCALLBACK(void) hmR0DummyThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit) 218 { 219 RT_NOREF(enmEvent, pVCpu, fGlobalInit); 220 } 221 222 static DECLCALLBACK(int) hmR0DummyEnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, 223 bool fEnabledBySystem, PCSUPHWVIRTMSRS pHwvirtMsrs) 224 { 225 RT_NOREF(pHostCpu, pVM, pvCpuPage, HCPhysCpuPage, fEnabledBySystem, pHwvirtMsrs); 226 return VINF_SUCCESS; 227 } 228 229 static DECLCALLBACK(int) hmR0DummyDisableCpu(PHMPHYSCPU pHostCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage) 230 { 231 RT_NOREF(pHostCpu, pvCpuPage, HCPhysCpuPage); 232 return VINF_SUCCESS; 233 } 234 235 static DECLCALLBACK(int) hmR0DummyInitVM(PVMCC pVM) 236 { 237 RT_NOREF(pVM); 238 return VINF_SUCCESS; 239 } 240 241 static DECLCALLBACK(int) hmR0DummyTermVM(PVMCC pVM) 242 { 243 RT_NOREF(pVM); 244 return VINF_SUCCESS; 245 } 246 247 static DECLCALLBACK(int) hmR0DummySetupVM(PVMCC pVM) 248 { 249 RT_NOREF(pVM); 250 return VINF_SUCCESS; 251 } 252 253 static DECLCALLBACK(int) hmR0DummyCallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation) 254 { 255 RT_NOREF(pVCpu, enmOperation); 256 return VINF_SUCCESS; 257 } 258 259 static DECLCALLBACK(VBOXSTRICTRC) hmR0DummyRunGuestCode(PVMCPUCC pVCpu) 260 { 261 RT_NOREF(pVCpu); 262 return VERR_NOT_SUPPORTED; 263 } 264 265 static DECLCALLBACK(int) hmR0DummyExportHostState(PVMCPUCC pVCpu) 266 { 267 RT_NOREF(pVCpu); 268 return VINF_SUCCESS; 269 } 270 271 /** Dummy ops. */ 272 static HMR0VTABLE const g_HmR0OpsDummy = 273 { 274 /* .pfnEnterSession = */ hmR0DummyEnter, 275 /* .pfnThreadCtxCallback = */ hmR0DummyThreadCtxCallback, 276 /* .pfnCallRing3Callback = */ hmR0DummyCallRing3Callback, 277 /* .pfnExportHostState = */ hmR0DummyExportHostState, 278 /* .pfnRunGuestCode = */ hmR0DummyRunGuestCode, 279 /* .pfnEnableCpu = */ hmR0DummyEnableCpu, 280 /* .pfnDisableCpu = */ hmR0DummyDisableCpu, 281 /* .pfnInitVM = */ hmR0DummyInitVM, 282 /* .pfnTermVM = */ hmR0DummyTermVM, 283 /* .pfnSetupVM = */ hmR0DummySetupVM, 284 }; 285 286 /** @} */ 171 287 172 288 … … 226 342 227 343 228 /** @name Dummy callback handlers. 229 * @{ */ 230 231 static DECLCALLBACK(int) hmR0DummyEnter(PVMCPUCC pVCpu) 232 { 233 RT_NOREF1(pVCpu); 234 return VINF_SUCCESS; 235 } 236 237 static DECLCALLBACK(void) hmR0DummyThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit) 238 { 239 RT_NOREF3(enmEvent, pVCpu, fGlobalInit); 240 } 241 242 static DECLCALLBACK(int) hmR0DummyEnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, 243 bool fEnabledBySystem, PCSUPHWVIRTMSRS pHwvirtMsrs) 244 { 245 RT_NOREF6(pHostCpu, pVM, pvCpuPage, HCPhysCpuPage, fEnabledBySystem, pHwvirtMsrs); 246 return VINF_SUCCESS; 247 } 248 249 static DECLCALLBACK(int) hmR0DummyDisableCpu(PHMPHYSCPU pHostCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage) 250 { 251 RT_NOREF3(pHostCpu, pvCpuPage, HCPhysCpuPage); 252 return VINF_SUCCESS; 253 } 254 255 static DECLCALLBACK(int) hmR0DummyInitVM(PVMCC pVM) 256 { 257 RT_NOREF1(pVM); 258 return VINF_SUCCESS; 259 } 260 261 static DECLCALLBACK(int) hmR0DummyTermVM(PVMCC pVM) 262 { 263 RT_NOREF1(pVM); 264 return VINF_SUCCESS; 265 } 266 267 static DECLCALLBACK(int) hmR0DummySetupVM(PVMCC pVM) 268 { 269 RT_NOREF1(pVM); 270 return VINF_SUCCESS; 271 } 272 273 static DECLCALLBACK(int) hmR0DummyCallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation) 274 { 275 RT_NOREF2(pVCpu, enmOperation); 276 return VINF_SUCCESS; 277 } 278 279 static DECLCALLBACK(VBOXSTRICTRC) hmR0DummyRunGuestCode(PVMCPUCC pVCpu) 280 { 281 RT_NOREF(pVCpu); 282 return VINF_SUCCESS; 283 } 284 285 static DECLCALLBACK(int) hmR0DummyExportHostState(PVMCPUCC pVCpu) 286 { 287 RT_NOREF1(pVCpu); 288 return VINF_SUCCESS; 289 } 290 291 /** @} */ 344 345 /** 346 * Worker function used by hmR0PowerCallback() and HMR0Init() to initalize VT-x 347 * on a CPU. 348 * 349 * @param idCpu The identifier for the CPU the function is called on. 350 * @param pvUser1 Pointer to the first RC structure. 351 * @param pvUser2 Ignored. 352 */ 353 static DECLCALLBACK(void) hmR0InitIntelCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2) 354 { 355 PHMR0FIRSTRC pFirstRc = (PHMR0FIRSTRC)pvUser1; 356 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 357 Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /** @todo fix idCpu == index assumption (rainy day) */ 358 NOREF(idCpu); NOREF(pvUser2); 359 360 int rc = SUPR0GetVmxUsability(NULL /* pfIsSmxModeAmbiguous */); 361 hmR0FirstRcSetStatus(pFirstRc, rc); 362 } 292 363 293 364 … … 306 377 * (This is only supported by some Mac OS X kernels atm.) 307 378 */ 308 int rc = g_HmR0.rcInit = SUPR0EnableVTx(true /* fEnable */); 379 int rc; 380 g_HmR0.rcInit = rc = SUPR0EnableVTx(true /* fEnable */); 309 381 g_HmR0.hwvirt.u.vmx.fUsingSUPR0EnableVTx = rc != VERR_NOT_SUPPORTED; 310 382 if (g_HmR0.hwvirt.u.vmx.fUsingSUPR0EnableVTx) … … 316 388 rc = SUPR0EnableVTx(false /* fEnable */); 317 389 AssertLogRelRC(rc); 390 rc = VINF_SUCCESS; 318 391 } 319 392 } … … 322 395 HMR0FIRSTRC FirstRc; 323 396 hmR0FirstRcInit(&FirstRc); 324 g_HmR0.rcInit = RTMpOnAll(hmR0InitIntelCpu, &FirstRc, NULL);325 if (RT_SUCCESS( g_HmR0.rcInit))326 g_HmR0.rcInit = hmR0FirstRcGetStatus(&FirstRc);327 } 328 329 if (RT_SUCCESS( g_HmR0.rcInit))397 g_HmR0.rcInit = rc = RTMpOnAll(hmR0InitIntelCpu, &FirstRc, NULL); 398 if (RT_SUCCESS(rc)) 399 g_HmR0.rcInit = rc = hmR0FirstRcGetStatus(&FirstRc); 400 } 401 402 if (RT_SUCCESS(rc)) 330 403 { 331 404 /* Read CR4 and EFER for logging/diagnostic purposes. */ … … 416 489 { 417 490 rc = VMXR0GlobalInit(); 418 if (RT_FAILURE(rc)) 491 if (RT_SUCCESS(rc)) 492 { 493 /* 494 * Install the VT-x methods. 495 */ 496 g_HmR0Ops = g_HmR0OpsVmx; 497 498 /* 499 * Check for the VMX-Preemption Timer and adjust for the "VMX-Preemption 500 * Timer Does Not Count Down at the Rate Specified" CPU erratum. 501 */ 502 VMXCTLSMSR PinCtls; 503 PinCtls.u = g_HmR0.hwvirt.Msrs.u.vmx.u64PinCtls; 504 if (PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER) 505 { 506 uint64_t const uVmxMiscMsr = g_HmR0.hwvirt.Msrs.u.vmx.u64Misc; 507 g_HmR0.hwvirt.u.vmx.fUsePreemptTimer = true; 508 g_HmR0.hwvirt.u.vmx.cPreemptTimerShift = RT_BF_GET(uVmxMiscMsr, VMX_BF_MISC_PREEMPT_TIMER_TSC); 509 if (HMIsSubjectToVmxPreemptTimerErratum()) 510 g_HmR0.hwvirt.u.vmx.cPreemptTimerShift = 0; /* This is about right most of the time here. */ 511 } 512 } 513 else 514 { 419 515 g_HmR0.rcInit = rc; 420 421 /* 422 * Install the VT-x methods. 423 */ 424 g_HmR0.pfnEnterSession = VMXR0Enter; 425 g_HmR0.pfnThreadCtxCallback = VMXR0ThreadCtxCallback; 426 g_HmR0.pfnCallRing3Callback = VMXR0CallRing3Callback; 427 g_HmR0.pfnExportHostState = VMXR0ExportHostState; 428 g_HmR0.pfnRunGuestCode = VMXR0RunGuestCode; 429 g_HmR0.pfnEnableCpu = VMXR0EnableCpu; 430 g_HmR0.pfnDisableCpu = VMXR0DisableCpu; 431 g_HmR0.pfnInitVM = VMXR0InitVM; 432 g_HmR0.pfnTermVM = VMXR0TermVM; 433 g_HmR0.pfnSetupVM = VMXR0SetupVM; 434 435 /* 436 * Check for the VMX-Preemption Timer and adjust for the "VMX-Preemption 437 * Timer Does Not Count Down at the Rate Specified" CPU erratum. 438 */ 439 VMXCTLSMSR PinCtls; 440 PinCtls.u = g_HmR0.hwvirt.Msrs.u.vmx.u64PinCtls; 441 if (PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER) 442 { 443 uint64_t const uVmxMiscMsr = g_HmR0.hwvirt.Msrs.u.vmx.u64Misc; 444 g_HmR0.hwvirt.u.vmx.fUsePreemptTimer = true; 445 g_HmR0.hwvirt.u.vmx.cPreemptTimerShift = RT_BF_GET(uVmxMiscMsr, VMX_BF_MISC_PREEMPT_TIMER_TSC); 446 if (HMIsSubjectToVmxPreemptTimerErratum()) 447 g_HmR0.hwvirt.u.vmx.cPreemptTimerShift = 0; /* This is about right most of the time here. */ 516 g_fHmVmxSupported = false; 448 517 } 449 518 } … … 458 527 459 528 /** 529 * Worker function used by hmR0PowerCallback() and HMR0Init() to initalize AMD-V 530 * on a CPU. 531 * 532 * @param idCpu The identifier for the CPU the function is called on. 533 * @param pvUser1 Pointer to the first RC structure. 534 * @param pvUser2 Ignored. 535 */ 536 static DECLCALLBACK(void) hmR0InitAmdCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2) 537 { 538 PHMR0FIRSTRC pFirstRc = (PHMR0FIRSTRC)pvUser1; 539 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD)); 540 Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /** @todo fix idCpu == index assumption (rainy day) */ 541 NOREF(idCpu); NOREF(pvUser2); 542 543 int rc = SUPR0GetSvmUsability(true /* fInitSvm */); 544 hmR0FirstRcSetStatus(pFirstRc, rc); 545 } 546 547 548 /** 460 549 * AMD-specific initialization code. 461 550 * … … 466 555 /* Call the global AMD-V initialization routine (should only fail in out-of-memory situations). */ 467 556 int rc = SVMR0GlobalInit(); 468 if (RT_FAILURE(rc)) 469 { 557 if (RT_SUCCESS(rc)) 558 { 559 /* 560 * Install the AMD-V methods. 561 */ 562 g_HmR0Ops = g_HmR0OpsSvm; 563 564 /* Query AMD features. */ 565 uint32_t u32Dummy; 566 ASMCpuId(0x8000000a, &g_HmR0.hwvirt.u.svm.u32Rev, &g_uHmMaxAsid, &u32Dummy, &g_HmR0.hwvirt.u.svm.u32Features); 567 568 /* 569 * We need to check if AMD-V has been properly initialized on all CPUs. 570 * Some BIOSes might do a poor job. 571 */ 572 HMR0FIRSTRC FirstRc; 573 hmR0FirstRcInit(&FirstRc); 574 rc = RTMpOnAll(hmR0InitAmdCpu, &FirstRc, NULL); 575 AssertRC(rc); 576 if (RT_SUCCESS(rc)) 577 rc = hmR0FirstRcGetStatus(&FirstRc); 578 #ifndef DEBUG_bird 579 AssertMsg(rc == VINF_SUCCESS || rc == VERR_SVM_IN_USE, 580 ("hmR0InitAmdCpu failed for cpu %d with rc=%Rrc\n", hmR0FirstRcGetCpuId(&FirstRc), rc)); 581 #endif 582 if (RT_SUCCESS(rc)) 583 { 584 SUPR0GetHwvirtMsrs(&g_HmR0.hwvirt.Msrs, SUPVTCAPS_AMD_V, false /* fForce */); 585 g_fHmSvmSupported = true; 586 } 587 else 588 { 589 g_HmR0.rcInit = rc; 590 if (rc == VERR_SVM_DISABLED || rc == VERR_SVM_IN_USE) 591 rc = VINF_SUCCESS; /* Don't fail if AMD-V is disabled or in use. */ 592 } 593 } 594 else 470 595 g_HmR0.rcInit = rc; 471 return rc;472 }473 474 /*475 * Install the AMD-V methods.476 */477 g_HmR0.pfnEnterSession = SVMR0Enter;478 g_HmR0.pfnThreadCtxCallback = SVMR0ThreadCtxCallback;479 g_HmR0.pfnCallRing3Callback = SVMR0CallRing3Callback;480 g_HmR0.pfnExportHostState = SVMR0ExportHostState;481 g_HmR0.pfnRunGuestCode = SVMR0RunGuestCode;482 g_HmR0.pfnEnableCpu = SVMR0EnableCpu;483 g_HmR0.pfnDisableCpu = SVMR0DisableCpu;484 g_HmR0.pfnInitVM = SVMR0InitVM;485 g_HmR0.pfnTermVM = SVMR0TermVM;486 g_HmR0.pfnSetupVM = SVMR0SetupVM;487 488 /* Query AMD features. */489 uint32_t u32Dummy;490 ASMCpuId(0x8000000a, &g_HmR0.hwvirt.u.svm.u32Rev, &g_uHmMaxAsid, &u32Dummy, &g_HmR0.hwvirt.u.svm.u32Features);491 492 /*493 * We need to check if AMD-V has been properly initialized on all CPUs.494 * Some BIOSes might do a poor job.495 */496 HMR0FIRSTRC FirstRc;497 hmR0FirstRcInit(&FirstRc);498 rc = RTMpOnAll(hmR0InitAmdCpu, &FirstRc, NULL);499 AssertRC(rc);500 if (RT_SUCCESS(rc))501 rc = hmR0FirstRcGetStatus(&FirstRc);502 #ifndef DEBUG_bird503 AssertMsg(rc == VINF_SUCCESS || rc == VERR_SVM_IN_USE,504 ("hmR0InitAmdCpu failed for cpu %d with rc=%Rrc\n", hmR0FirstRcGetCpuId(&FirstRc), rc));505 #endif506 if (RT_SUCCESS(rc))507 {508 SUPR0GetHwvirtMsrs(&g_HmR0.hwvirt.Msrs, SUPVTCAPS_AMD_V, false /* fForce */);509 g_fHmSvmSupported = true;510 }511 else512 {513 g_HmR0.rcInit = rc;514 if (rc == VERR_SVM_DISABLED || rc == VERR_SVM_IN_USE)515 rc = VINF_SUCCESS; /* Don't fail if AMD-V is disabled or in use. */516 }517 596 return rc; 518 597 } … … 546 625 547 626 /* Fill in all callbacks with placeholders. */ 548 g_HmR0.pfnEnterSession = hmR0DummyEnter; 549 g_HmR0.pfnThreadCtxCallback = hmR0DummyThreadCtxCallback; 550 g_HmR0.pfnCallRing3Callback = hmR0DummyCallRing3Callback; 551 g_HmR0.pfnExportHostState = hmR0DummyExportHostState; 552 g_HmR0.pfnRunGuestCode = hmR0DummyRunGuestCode; 553 g_HmR0.pfnEnableCpu = hmR0DummyEnableCpu; 554 g_HmR0.pfnDisableCpu = hmR0DummyDisableCpu; 555 g_HmR0.pfnInitVM = hmR0DummyInitVM; 556 g_HmR0.pfnTermVM = hmR0DummyTermVM; 557 g_HmR0.pfnSetupVM = hmR0DummySetupVM; 627 g_HmR0Ops = g_HmR0OpsDummy; 558 628 559 629 /* Default is global VT-x/AMD-V init. */ 560 g_HmR0.fGlobalInit 630 g_HmR0.fGlobalInit = true; 561 631 562 632 g_fHmVmxSupported = false; … … 582 652 { 583 653 if (fCaps & SUPVTCAPS_VT_X) 584 {585 654 rc = hmR0InitIntel(); 586 if (RT_FAILURE(rc))587 return rc;588 }589 655 else 590 656 { 591 657 Assert(fCaps & SUPVTCAPS_AMD_V); 592 658 rc = hmR0InitAmd(); 593 if (RT_FAILURE(rc))594 return rc;595 659 } 660 if (RT_SUCCESS(rc)) 661 { 662 /* 663 * Register notification callbacks that we can use to disable/enable CPUs 664 * when brought offline/online or suspending/resuming. 665 */ 666 if (!g_HmR0.hwvirt.u.vmx.fUsingSUPR0EnableVTx) 667 { 668 rc = RTMpNotificationRegister(hmR0MpEventCallback, NULL); 669 if (RT_SUCCESS(rc)) 670 { 671 rc = RTPowerNotificationRegister(hmR0PowerCallback, NULL); 672 if (RT_FAILURE(rc)) 673 RTMpNotificationDeregister(hmR0MpEventCallback, NULL); 674 } 675 if (RT_FAILURE(rc)) 676 { 677 /* There shouldn't be any per-cpu allocations at this point, 678 so just have to call SVMR0GlobalTerm and VMXR0GlobalTerm. */ 679 if (fCaps & SUPVTCAPS_VT_X) 680 VMXR0GlobalTerm(); 681 else 682 SVMR0GlobalTerm(); 683 g_HmR0Ops = g_HmR0OpsDummy; 684 g_HmR0.rcInit = rc; 685 g_fHmSvmSupported = false; 686 g_fHmVmxSupported = false; 687 } 688 } 689 } 596 690 } 597 691 else 598 g_HmR0.rcInit = VERR_UNSUPPORTED_CPU; 599 600 /* 601 * Register notification callbacks that we can use to disable/enable CPUs 602 * when brought offline/online or suspending/resuming. 603 */ 604 if (!g_HmR0.hwvirt.u.vmx.fUsingSUPR0EnableVTx) 605 { 606 rc = RTMpNotificationRegister(hmR0MpEventCallback, NULL); 607 AssertRC(rc); 608 609 rc = RTPowerNotificationRegister(hmR0PowerCallback, NULL); 610 AssertRC(rc); 611 } 612 613 /* We return success here because module init shall not fail if HM fails to initialize. */ 614 return VINF_SUCCESS; 692 { 693 g_HmR0.rcInit = rc; 694 rc = VINF_SUCCESS; /* We return success here because module init shall not fail if HM fails to initialize. */ 695 } 696 return rc; 615 697 } 616 698 … … 619 701 * Does global Ring-0 HM termination (at module termination). 620 702 * 621 * @returns VBox status code .703 * @returns VBox status code (ignored). 622 704 */ 623 705 VMMR0_INT_DECL(int) HMR0Term(void) … … 651 733 652 734 /* Doesn't really matter if this fails. */ 653 rc = RTMpNotificationDeregister(hmR0MpEventCallback, NULL); AssertRC(rc); 654 rc = RTPowerNotificationDeregister(hmR0PowerCallback, NULL); AssertRC(rc); 735 RTMpNotificationDeregister(hmR0MpEventCallback, NULL); 736 RTPowerNotificationDeregister(hmR0PowerCallback, NULL); 737 rc = VINF_SUCCESS; 655 738 656 739 /* … … 705 788 706 789 /** 707 * Worker function used by hmR0PowerCallback() and HMR0Init() to initalize VT-x708 * on a CPU.709 *710 * @param idCpu The identifier for the CPU the function is called on.711 * @param pvUser1 Pointer to the first RC structure.712 * @param pvUser2 Ignored.713 */714 static DECLCALLBACK(void) hmR0InitIntelCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)715 {716 PHMR0FIRSTRC pFirstRc = (PHMR0FIRSTRC)pvUser1;717 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));718 Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /** @todo fix idCpu == index assumption (rainy day) */719 NOREF(idCpu); NOREF(pvUser2);720 721 int rc = SUPR0GetVmxUsability(NULL /* pfIsSmxModeAmbiguous */);722 hmR0FirstRcSetStatus(pFirstRc, rc);723 }724 725 726 /**727 * Worker function used by hmR0PowerCallback() and HMR0Init() to initalize AMD-V728 * on a CPU.729 *730 * @param idCpu The identifier for the CPU the function is called on.731 * @param pvUser1 Pointer to the first RC structure.732 * @param pvUser2 Ignored.733 */734 static DECLCALLBACK(void) hmR0InitAmdCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)735 {736 PHMR0FIRSTRC pFirstRc = (PHMR0FIRSTRC)pvUser1;737 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));738 Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /** @todo fix idCpu == index assumption (rainy day) */739 NOREF(idCpu); NOREF(pvUser2);740 741 int rc = SUPR0GetSvmUsability(true /* fInitSvm */);742 hmR0FirstRcSetStatus(pFirstRc, rc);743 }744 745 746 /**747 790 * Enable VT-x or AMD-V on the current CPU 748 791 * … … 768 811 if ( g_fHmVmxSupported 769 812 && g_HmR0.hwvirt.u.vmx.fUsingSUPR0EnableVTx) 770 rc = g_HmR0 .pfnEnableCpu(pHostCpu, pVM, NULL /* pvCpuPage */, NIL_RTHCPHYS, true, &g_HmR0.hwvirt.Msrs);813 rc = g_HmR0Ops.pfnEnableCpu(pHostCpu, pVM, NULL /* pvCpuPage */, NIL_RTHCPHYS, true, &g_HmR0.hwvirt.Msrs); 771 814 else 772 815 { 773 816 AssertLogRelMsgReturn(pHostCpu->hMemObj != NIL_RTR0MEMOBJ, ("hmR0EnableCpu failed idCpu=%u.\n", idCpu), VERR_HM_IPE_1); 774 rc = g_HmR0 .pfnEnableCpu(pHostCpu, pVM, pHostCpu->pvMemObj, pHostCpu->HCPhysMemObj, false, &g_HmR0.hwvirt.Msrs);817 rc = g_HmR0Ops.pfnEnableCpu(pHostCpu, pVM, pHostCpu->pvMemObj, pHostCpu->HCPhysMemObj, false, &g_HmR0.hwvirt.Msrs); 775 818 } 776 819 if (RT_SUCCESS(rc)) … … 958 1001 if (pHostCpu->fConfigured) 959 1002 { 960 rc = g_HmR0 .pfnDisableCpu(pHostCpu, pHostCpu->pvMemObj, pHostCpu->HCPhysMemObj);1003 rc = g_HmR0Ops.pfnDisableCpu(pHostCpu, pHostCpu->pvMemObj, pHostCpu->HCPhysMemObj); 961 1004 AssertRCReturn(rc, rc); 962 1005 … … 1258 1301 * Call the hardware specific initialization method. 1259 1302 */ 1260 return g_HmR0 .pfnInitVM(pVM);1303 return g_HmR0Ops.pfnInitVM(pVM); 1261 1304 } 1262 1305 … … 1279 1322 * mess with VT-x/AMD-V features on the CPU, currently all they do is free memory so this is safe. 1280 1323 */ 1281 return g_HmR0 .pfnTermVM(pVM);1324 return g_HmR0Ops.pfnTermVM(pVM); 1282 1325 } 1283 1326 … … 1324 1367 1325 1368 /* Setup VT-x or AMD-V. */ 1326 rc = g_HmR0 .pfnSetupVM(pVM);1369 rc = g_HmR0Ops.pfnSetupVM(pVM); 1327 1370 1328 1371 /* Disable VT-x or AMD-V if local init was done before. */ … … 1351 1394 RT_NOREF(pvUser); 1352 1395 Assert(pVCpu); 1353 Assert(g_HmR0 .pfnCallRing3Callback);1354 return g_HmR0 .pfnCallRing3Callback(pVCpu, enmOperation);1396 Assert(g_HmR0Ops.pfnCallRing3Callback); 1397 return g_HmR0Ops.pfnCallRing3Callback(pVCpu, enmOperation); 1355 1398 } 1356 1399 … … 1424 1467 1425 1468 /* Keep track of the CPU owning the VMCS for debugging scheduling weirdness and ring-3 calls. */ 1426 rc = g_HmR0 .pfnEnterSession(pVCpu);1469 rc = g_HmR0Ops.pfnEnterSession(pVCpu); 1427 1470 AssertMsgRCReturnStmt(rc, ("rc=%Rrc pVCpu=%p\n", rc, pVCpu), pVCpu->hmr0.s.idEnteredCpu = NIL_RTCPUID, rc); 1428 1471 1429 1472 /* Exports the host-state as we may be resuming code after a longjmp and quite 1430 1473 possibly now be scheduled on a different CPU. */ 1431 rc = g_HmR0 .pfnExportHostState(pVCpu);1474 rc = g_HmR0Ops.pfnExportHostState(pVCpu); 1432 1475 AssertMsgRCReturnStmt(rc, ("rc=%Rrc pVCpu=%p\n", rc, pVCpu), pVCpu->hmr0.s.idEnteredCpu = NIL_RTCPUID, rc); 1433 1476 … … 1489 1532 PVMCPUCC pVCpu = (PVMCPUCC)pvUser; 1490 1533 Assert(pVCpu); 1491 Assert(g_HmR0 .pfnThreadCtxCallback);1492 1493 g_HmR0 .pfnThreadCtxCallback(enmEvent, pVCpu, g_HmR0.fGlobalInit);1534 Assert(g_HmR0Ops.pfnThreadCtxCallback); 1535 1536 g_HmR0Ops.pfnThreadCtxCallback(enmEvent, pVCpu, g_HmR0.fGlobalInit); 1494 1537 } 1495 1538 … … 1527 1570 #endif 1528 1571 1529 VBOXSTRICTRC rcStrict = g_HmR0 .pfnRunGuestCode(pVCpu);1572 VBOXSTRICTRC rcStrict = g_HmR0Ops.pfnRunGuestCode(pVCpu); 1530 1573 1531 1574 #ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
Note:
See TracChangeset
for help on using the changeset viewer.