Changeset 36245 in vbox
- Timestamp:
- Mar 9, 2011 8:22:00 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 70469
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/HWACCMR0.cpp
r36237 r36245 34 34 #include <iprt/asm-amd64-x86.h> 35 35 #include <iprt/cpuset.h> 36 #include <iprt/mem.h> 36 37 #include <iprt/memobj.h> 37 38 #include <iprt/param.h> … … 47 48 static DECLCALLBACK(void) hwaccmR0EnableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2); 48 49 static DECLCALLBACK(void) hwaccmR0DisableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2); 49 static DECLCALLBACK(void) HWACCMR0InitCPU(RTCPUID idCpu, void *pvUser1, void *pvUser2); 50 static int hwaccmR0CheckCpuRcArray(int *paRc, unsigned cErrorCodes, RTCPUID *pidCpu); 50 static DECLCALLBACK(void) hwaccmR0InitCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2); 51 51 static bool hwaccmR0IsSubjectToVmxPreemptionTimerErratum(void); 52 52 static DECLCALLBACK(void) hwaccmR0PowerCallback(RTPOWEREVENT enmEvent, void *pvUser); … … 143 143 144 144 145 /** 146 * This is used to manage the status code of a RTMpOnAll in HWACCM. 147 */ 148 typedef struct HWACCMR0FIRSTRC 149 { 150 /** The status code. */ 151 int32_t volatile rc; 152 /** The ID of the CPU reporting the first failure. */ 153 RTCPUID volatile idCpu; 154 } HWACCMR0FIRSTRC; 155 /** Pointer to a first return code structure. */ 156 typedef HWACCMR0FIRSTRC *PHWACCMR0FIRSTRC; 157 158 159 /** 160 * Initializes a first return code structure. 161 * 162 * @param pFirstRc The structure to init. 163 */ 164 static void hwaccmR0FirstRcInit(PHWACCMR0FIRSTRC pFirstRc) 165 { 166 pFirstRc->rc = VINF_SUCCESS; 167 pFirstRc->idCpu = NIL_RTCPUID; 168 } 169 170 171 /** 172 * Try se the status code (success ignored). 173 * 174 * @param pFirstRc The first return code structure. 175 * @param rc The status code. 176 */ 177 static void hwaccmR0FirstRcSetStatus(PHWACCMR0FIRSTRC pFirstRc, int rc) 178 { 179 if ( RT_FAILURE(rc) 180 && ASMAtomicCmpXchgS32(&pFirstRc->rc, rc, VINF_SUCCESS)) 181 pFirstRc->idCpu = RTMpCpuId(); 182 } 183 184 185 /** 186 * Get the status code of a first return code structure. 187 * 188 * @returns The status code; VINF_SUCCESS or error status, no informational or 189 * warning errors. 190 * @param pFirstRc The first return code structure. 191 */ 192 static int hwaccmR0FirstRcGetStatus(PHWACCMR0FIRSTRC pFirstRc) 193 { 194 return pFirstRc->rc; 195 } 196 197 198 /** 199 * Get the CPU ID on which the failure status code was reported. 200 * 201 * @returns The CPU ID, NIL_RTCPUID if no failure was reported. 202 * @param pFirstRc The first return code structure. 203 */ 204 static RTCPUID hwaccmR0FirstRcGetCpuId(PHWACCMR0FIRSTRC pFirstRc) 205 { 206 return pFirstRc->idCpu; 207 } 208 145 209 146 210 /** … … 211 275 ) 212 276 { 213 int aRc[RTCPUSET_MAX_CPUS]; /** @todo 256 CPUs: move this off the stack */214 RTCPUID idCpu = 0;215 216 277 HWACCMR0Globals.vmx.msr.feature_ctrl = ASMRdMsr(MSR_IA32_FEATURE_CONTROL); 217 278 … … 237 298 238 299 /* We need to check if VT-x has been properly initialized on all CPUs. Some BIOSes do a lousy job. */ 239 memset(aRc, 0, sizeof(aRc)); 240 HWACCMR0Globals.lLastError = RTMpOnAll(HWACCMR0InitCPU, (void *)u32VendorEBX, aRc); 241 242 /* Check the return code of all invocations. */ 300 HWACCMR0FIRSTRC FirstRc; 301 hwaccmR0FirstRcInit(&FirstRc); 302 HWACCMR0Globals.lLastError = RTMpOnAll(hwaccmR0InitCpu, (void *)u32VendorEBX, &FirstRc); 243 303 if (RT_SUCCESS(HWACCMR0Globals.lLastError)) 244 HWACCMR0Globals.lLastError = hwaccmR0 CheckCpuRcArray(aRc, RT_ELEMENTS(aRc), &idCpu);304 HWACCMR0Globals.lLastError = hwaccmR0FirstRcGetStatus(&FirstRc); 245 305 } 246 306 if (RT_SUCCESS(HWACCMR0Globals.lLastError)) … … 355 415 #ifdef LOG_ENABLED 356 416 else 357 SUPR0Printf(" HWACCMR0InitCPUfailed with rc=%d\n", HWACCMR0Globals.lLastError);417 SUPR0Printf("hwaccmR0InitCpu failed with rc=%d\n", HWACCMR0Globals.lLastError); 358 418 #endif 359 419 } … … 376 436 ) 377 437 { 378 int aRc[RTCPUSET_MAX_CPUS]; /** @todo 256 CPUs: Move this off the stack */379 RTCPUID idCpu = 0;380 381 438 fAMDVPresent = true; 382 439 … … 385 442 386 443 /* We need to check if AMD-V has been properly initialized on all CPUs. Some BIOSes might do a poor job. */ 387 memset(aRc, 0, sizeof(aRc)); 388 rc = RTMpOnAll(HWACCMR0InitCPU, (void *)u32VendorEBX, aRc); 389 AssertRC(rc); 390 391 /* Check the return code of all invocations. */ 444 HWACCMR0FIRSTRC FirstRc; 445 hwaccmR0FirstRcInit(&FirstRc); 446 rc = RTMpOnAll(hwaccmR0InitCpu, (void *)u32VendorEBX, &FirstRc); AssertRC(rc); 392 447 if (RT_SUCCESS(rc)) 393 rc = hwaccmR0CheckCpuRcArray(aRc, RT_ELEMENTS(aRc), &idCpu); 394 448 rc = hwaccmR0FirstRcGetStatus(&FirstRc); 395 449 #ifndef DEBUG_bird 396 AssertMsg(rc == VINF_SUCCESS || rc == VERR_SVM_IN_USE, (" HWACCMR0InitCPU failed for cpu %d with rc=%d\n", idCpu, rc));450 AssertMsg(rc == VINF_SUCCESS || rc == VERR_SVM_IN_USE, ("hwaccmR0InitCpu failed for cpu %d with rc=%d\n", hwaccmR0FirstRcGetCpuId(&FirstRc), rc)); 397 451 #endif 398 452 if (RT_SUCCESS(rc)) … … 449 503 450 504 return VINF_SUCCESS; 451 }452 453 454 /**455 * Checks the error code array filled in for each cpu in the system.456 *457 * @returns VBox status code.458 * @param paRc Error code array459 * @param cErrorCodes Array size460 * @param pidCpu Value of the first cpu that set an error (out)461 */462 static int hwaccmR0CheckCpuRcArray(int *paRc, unsigned cErrorCodes, RTCPUID *pidCpu)463 {464 int rc = VINF_SUCCESS;465 466 Assert(cErrorCodes == RTCPUSET_MAX_CPUS);467 468 for (unsigned i=0;i<cErrorCodes;i++)469 {470 if (RTMpIsCpuOnline(i))471 {472 if (RT_FAILURE(paRc[i]))473 {474 rc = paRc[i];475 *pidCpu = i;476 break;477 }478 }479 }480 return rc;481 505 } 482 506 … … 560 584 if (HWACCMR0Globals.fGlobalInit) 561 585 { 562 int aRc[RTCPUSET_MAX_CPUS]; /** @todo 256 CPUs: Move this off the stack */ 563 564 memset(aRc, 0, sizeof(aRc)); 565 rc = RTMpOnAll(hwaccmR0DisableCpuCallback, aRc, NULL); 586 HWACCMR0FIRSTRC FirstRc; 587 hwaccmR0FirstRcInit(&FirstRc); 588 rc = RTMpOnAll(hwaccmR0DisableCpuCallback, NULL, &FirstRc); 566 589 Assert(RT_SUCCESS(rc) || rc == VERR_NOT_SUPPORTED); 567 #ifdef VBOX_STRICT 568 for (unsigned i=0;i<RT_ELEMENTS(HWACCMR0Globals.aCpuInfo);i++) 569 AssertMsgRC(aRc[i], ("hwaccmR0DisableCpuCallback failed for cpu %d with rc=%d\n", i, aRc[i])); 570 #endif 590 if (RT_SUCCESS(rc)) 591 { 592 rc = hwaccmR0FirstRcGetStatus(&FirstRc); 593 AssertMsgRC(rc, ("%u: %Rrc\n", hwaccmR0FirstRcGetCpuId(&FirstRc), rc)); 594 } 571 595 } 572 596 … … 593 617 * @param pvUser2 The 2nd user argument. 594 618 */ 595 static DECLCALLBACK(void) HWACCMR0InitCPU(RTCPUID idCpu, void *pvUser1, void *pvUser2) 596 { 597 unsigned u32VendorEBX = (uintptr_t)pvUser1; 598 int *paRc = (int *)pvUser2; 599 uint64_t val; 619 static DECLCALLBACK(void) hwaccmR0InitCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2) 620 { 621 unsigned u32VendorEBX = (uintptr_t)pvUser1; 622 PHWACCMR0FIRSTRC pFirstRc = (PHWACCMR0FIRSTRC)pvUser2; 623 uint64_t val; 624 int rc; 600 625 601 626 #if defined(LOG_ENABLED) && !defined(DEBUG_bird) 602 SUPR0Printf(" HWACCMR0InitCPUcpu %d\n", idCpu);627 SUPR0Printf("hwaccmR0InitCpu cpu %d\n", idCpu); 603 628 #endif 604 629 Assert(idCpu == (RTCPUID)RTMpCpuIdToSetIndex(idCpu)); /// @todo fix idCpu == index assumption (rainy day) … … 622 647 if ( (val & (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK)) 623 648 == (MSR_IA32_FEATURE_CONTROL_VMXON|MSR_IA32_FEATURE_CONTROL_LOCK)) 624 paRc[idCpu]= VINF_SUCCESS;649 rc = VINF_SUCCESS; 625 650 else 626 paRc[idCpu] = VERR_VMX_MSR_LOCKED_OR_DISABLED; 627 } 628 else 629 if (u32VendorEBX == X86_CPUID_VENDOR_AMD_EBX) 651 rc = VERR_VMX_MSR_LOCKED_OR_DISABLED; 652 } 653 else if (u32VendorEBX == X86_CPUID_VENDOR_AMD_EBX) 630 654 { 631 655 /* Check if SVM is disabled */ … … 636 660 val = ASMRdMsr(MSR_K6_EFER); 637 661 if (val & MSR_K6_EFER_SVME) 638 { 639 paRc[idCpu] = VERR_SVM_IN_USE; 640 } 662 rc = VERR_SVM_IN_USE; 641 663 else 642 664 { … … 649 671 /* Restore previous value. */ 650 672 ASMWrMsr(MSR_K6_EFER, val & ~MSR_K6_EFER_SVME); 651 paRc[idCpu]= VINF_SUCCESS;673 rc = VINF_SUCCESS; 652 674 } 653 675 else 654 paRc[idCpu]= VERR_SVM_ILLEGAL_EFER_MSR;676 rc = VERR_SVM_ILLEGAL_EFER_MSR; 655 677 } 656 678 } 657 679 else 658 paRc[idCpu]= VERR_SVM_DISABLED;680 rc = VERR_SVM_DISABLED; 659 681 } 660 682 else 683 { 661 684 AssertFailed(); /* can't happen */ 662 return; 685 rc = VERR_INTERNAL_ERROR_5; 686 } 687 688 hwaccmR0FirstRcSetStatus(pFirstRc, rc); 663 689 } 664 690 … … 704 730 else 705 731 { 706 int aRc[RTCPUSET_MAX_CPUS]; /** @todo 256 CPUs: Move this off the stack */707 RTCPUID idCpu = 0;708 709 memset(aRc, 0, sizeof(aRc));710 711 732 /* Allocate one page per cpu for the global vt-x and amd-v pages */ 712 733 for (unsigned i=0;i<RT_ELEMENTS(HWACCMR0Globals.aCpuInfo);i++) … … 734 755 { 735 756 /* First time, so initialize each cpu/core */ 736 rc = RTMpOnAll(hwaccmR0EnableCpuCallback, (void *)pVM, aRc);737 738 /* Check the return code of all invocations. */757 HWACCMR0FIRSTRC FirstRc; 758 hwaccmR0FirstRcInit(&FirstRc); 759 rc = RTMpOnAll(hwaccmR0EnableCpuCallback, (void *)pVM, &FirstRc); 739 760 if (RT_SUCCESS(rc)) 740 rc = hwaccmR0 CheckCpuRcArray(aRc, RT_ELEMENTS(aRc), &idCpu);741 AssertMsgRC(rc, ("HWACCMR0EnableAllCpus failed for cpu %d with rc=%d\n", idCpu, rc));761 rc = hwaccmR0FirstRcGetStatus(&FirstRc); 762 AssertMsgRC(rc, ("HWACCMR0EnableAllCpus failed for cpu %d with rc=%d\n", hwaccmR0FirstRcGetCpuId(&FirstRc), rc)); 742 763 } 743 764 else … … 806 827 static DECLCALLBACK(void) hwaccmR0EnableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2) 807 828 { 808 PVM pVM = (PVM)pvUser1; /* can be NULL! */ 809 int *paRc = (int *)pvUser2; 810 811 if (!HWACCMR0Globals.fGlobalInit) 812 { 813 paRc[idCpu] = VINF_SUCCESS; 814 AssertFailed(); 815 return; 816 } 817 818 paRc[idCpu] = hwaccmR0EnableCpu(pVM, idCpu); 829 PVM pVM = (PVM)pvUser1; /* can be NULL! */ 830 PHWACCMR0FIRSTRC pFirstRc = (PHWACCMR0FIRSTRC)pvUser2; 831 AssertReturnVoid(HWACCMR0Globals.fGlobalInit); 832 hwaccmR0FirstRcSetStatus(pFirstRc, hwaccmR0EnableCpu(pVM, idCpu)); 819 833 } 820 834 … … 868 882 static DECLCALLBACK(void) hwaccmR0DisableCpuCallback(RTCPUID idCpu, void *pvUser1, void *pvUser2) 869 883 { 870 int *paRc = (int *)pvUser1; 871 872 if (!HWACCMR0Globals.fGlobalInit) 873 { 874 paRc[idCpu] = VINF_SUCCESS; 875 AssertFailed(); 876 return; 877 } 878 879 paRc[idCpu] = hwaccmR0DisableCpu(idCpu); 884 PHWACCMR0FIRSTRC pFirstRc = (PHWACCMR0FIRSTRC)pvUser2; 885 AssertReturnVoid(HWACCMR0Globals.fGlobalInit); 886 hwaccmR0FirstRcSetStatus(pFirstRc, hwaccmR0DisableCpu(idCpu)); 880 887 } 881 888 … … 903 910 if (HWACCMR0Globals.enmHwAccmState == HWACCMSTATE_ENABLED) 904 911 { 905 int aRc[RTCPUSET_MAX_CPUS]; /** @todo 256 CPUs: Move this off the stack */ 906 int rc; 907 RTCPUID idCpu; 908 909 memset(aRc, 0, sizeof(aRc)); 912 int rc; 913 HWACCMR0FIRSTRC FirstRc; 914 hwaccmR0FirstRcInit(&FirstRc); 915 910 916 if (enmEvent == RTPOWEREVENT_SUSPEND) 911 917 { … … 913 919 { 914 920 /* Turn off VT-x or AMD-V on all CPUs. */ 915 rc = RTMpOnAll(hwaccmR0DisableCpuCallback, aRc, NULL);921 rc = RTMpOnAll(hwaccmR0DisableCpuCallback, NULL, &FirstRc); 916 922 Assert(RT_SUCCESS(rc) || rc == VERR_NOT_SUPPORTED); 917 923 } … … 921 927 { 922 928 /* Reinit the CPUs from scratch as the suspend state might have messed with the MSRs. (lousy BIOSes as usual) */ 923 rc = RTMpOnAll(HWACCMR0InitCPU, (void *)((HWACCMR0Globals.vmx.fSupported) ? X86_CPUID_VENDOR_INTEL_EBX : X86_CPUID_VENDOR_AMD_EBX), aRc); 929 uintptr_t uFirstArg = HWACCMR0Globals.vmx.fSupported ? X86_CPUID_VENDOR_INTEL_EBX : X86_CPUID_VENDOR_AMD_EBX; 930 rc = RTMpOnAll(hwaccmR0InitCpu, (void *)uFirstArg , &FirstRc); 924 931 Assert(RT_SUCCESS(rc) || rc == VERR_NOT_SUPPORTED); 925 926 932 if (RT_SUCCESS(rc)) 927 rc = hwaccmR0 CheckCpuRcArray(aRc, RT_ELEMENTS(aRc), &idCpu);933 rc = hwaccmR0FirstRcGetStatus(&FirstRc); 928 934 #ifdef LOG_ENABLED 929 935 if (RT_FAILURE(rc)) 930 SUPR0Printf("hwaccmR0PowerCallback HWACCMR0InitCPU failed with %d\n", rc);936 SUPR0Printf("hwaccmR0PowerCallback hwaccmR0InitCpu failed with %Rc\n", rc); 931 937 #endif 932 938 … … 934 940 { 935 941 /* Turn VT-x or AMD-V back on on all CPUs. */ 936 rc = RTMpOnAll(hwaccmR0EnableCpuCallback, NULL, aRc);942 rc = RTMpOnAll(hwaccmR0EnableCpuCallback, NULL, &FirstRc /* output ignored */); 937 943 Assert(RT_SUCCESS(rc) || rc == VERR_NOT_SUPPORTED); 938 944 }
Note:
See TracChangeset
for help on using the changeset viewer.