Changeset 19395 in vbox
- Timestamp:
- May 5, 2009 8:28:42 PM (16 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/gvm.h
r19381 r19395 42 42 typedef struct GVMCPU 43 43 { 44 /* VCPU id (0 - (pVM->cCPUs - 1)*/45 uint32_tidCpu;44 /** VCPU id (0 - (pVM->cCPUs - 1). */ 45 VMCPUID idCpu; 46 46 47 47 /** Handle to the EMT thread. */ … … 83 83 /** The ring-0 mapping of the VM structure. */ 84 84 PVM pVM; 85 /** Number of VCPUs (same as pVM->cCPUs) */ 86 uint32_t cCPUs; 85 /** Number of Virtual CPUs, i.e. how many entries there are in aCpus. 86 * Same same as PVM::cCPUs. */ 87 uint32_t cCpus; 87 88 uint32_t padding; 88 89 -
trunk/include/VBox/gvmm.h
r19382 r19395 125 125 GVMMR0DECL(int) GVMMR0QueryConfig(PSUPDRVSESSION pSession, const char *pszName, uint64_t *pu64Value); 126 126 127 GVMMR0DECL(int) GVMMR0CreateVM(PSUPDRVSESSION pSession, uint32_t cC PUs, PVM *ppVM);127 GVMMR0DECL(int) GVMMR0CreateVM(PSUPDRVSESSION pSession, uint32_t cCpus, PVM *ppVM); 128 128 GVMMR0DECL(int) GVMMR0InitVM(PVM pVM); 129 129 GVMMR0DECL(void) GVMMR0DoneInitVM(PVM pVM); 130 130 GVMMR0DECL(bool) GVMMR0DoingTermVM(PVM pVM, PGVM pGVM); 131 131 GVMMR0DECL(int) GVMMR0DestroyVM(PVM pVM); 132 GVMMR0DECL(int) GVMMR0RegisterVCpu(PVM pVM, unsignedidCpu);132 GVMMR0DECL(int) GVMMR0RegisterVCpu(PVM pVM, VMCPUID idCpu); 133 133 GVMMR0DECL(PGVM) GVMMR0ByHandle(uint32_t hGVM); 134 134 GVMMR0DECL(PGVM) GVMMR0ByVM(PVM pVM); 135 GVMMR0DECL(int) GVMMR0ByVMAndEMT(PVM pVM, unsignedidCpu, PGVM *ppGVM);135 GVMMR0DECL(int) GVMMR0ByVMAndEMT(PVM pVM, VMCPUID idCpu, PGVM *ppGVM); 136 136 GVMMR0DECL(PVM) GVMMR0GetVMByHandle(uint32_t hGVM); 137 137 GVMMR0DECL(PVM) GVMMR0GetVMByEMT(RTNATIVETHREAD hEMT); 138 GVMMR0DECL(int) GVMMR0SchedHalt(PVM pVM, unsignedidCpu, uint64_t u64ExpireGipTime);139 GVMMR0DECL(int) GVMMR0SchedWakeUp(PVM pVM, unsignedidCpu);140 GVMMR0DECL(int) GVMMR0SchedPoll(PVM pVM, unsignedidCpu, bool fYield);138 GVMMR0DECL(int) GVMMR0SchedHalt(PVM pVM, VMCPUID idCpu, uint64_t u64ExpireGipTime); 139 GVMMR0DECL(int) GVMMR0SchedWakeUp(PVM pVM, VMCPUID idCpu); 140 GVMMR0DECL(int) GVMMR0SchedPoll(PVM pVM, VMCPUID idCpu, bool fYield); 141 141 GVMMR0DECL(int) GVMMR0QueryStatistics(PGVMMSTATS pStats, PSUPDRVSESSION pSession, PVM pVM); 142 142 GVMMR0DECL(int) GVMMR0ResetStatistics(PCGVMMSTATS pStats, PSUPDRVSESSION pSession, PVM pVM); … … 153 153 PSUPDRVSESSION pSession; 154 154 /** Number of virtual CPUs for the new VM. (IN) */ 155 uint32_t cC PUs;155 uint32_t cCpus; 156 156 /** Pointer to the ring-3 mapping of the shared VM structure on return. (OUT) */ 157 157 PVMR3 pVMR3; -
trunk/src/VBox/VMM/VM.cpp
r19322 r19395 237 237 /* 238 238 * Call vmR3CreateU in the EMT thread and wait for it to finish. 239 * 240 * Note! VMCPUID_ANY is used here because VMR3ReqQueueU would have trouble 241 * submitting a request to a specific VCPU without a pVM. So, to make 242 * sure init is running on EMT(0), vmR3EmulationThreadWithId makes sure 243 * that only EMT(0) is servicing VMCPUID_ANY requests when pVM is NULL. 239 244 */ 240 245 PVMREQ pReq; 241 rc = VMR3ReqCallU(pUVM, VMCPUID_ANY /* can't use CPU0 here as it's too early (pVM==0) */, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)vmR3CreateU,242 4,pUVM, cCPUs, pfnCFGMConstructor, pvUserCFGM);246 rc = VMR3ReqCallU(pUVM, VMCPUID_ANY, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)vmR3CreateU, 4, 247 pUVM, cCPUs, pfnCFGMConstructor, pvUserCFGM); 243 248 if (RT_SUCCESS(rc)) 244 249 { … … 379 384 * 380 385 * @returns VBox status code. 381 * @param cC PUs Number of virtual CPUs386 * @param cCpus Number of virtual CPUs 382 387 * @param ppUVM Where to store the UVM pointer. 383 388 */ 384 static int vmR3CreateUVM(uint32_t cC PUs, PUVM *ppUVM)389 static int vmR3CreateUVM(uint32_t cCpus, PUVM *ppUVM) 385 390 { 386 391 uint32_t i; … … 389 394 * Create and initialize the UVM. 390 395 */ 391 PUVM pUVM = (PUVM)RTMemAllocZ(RT_OFFSETOF(UVM, aCpus[cC PUs]));396 PUVM pUVM = (PUVM)RTMemAllocZ(RT_OFFSETOF(UVM, aCpus[cCpus])); 392 397 AssertReturn(pUVM, VERR_NO_MEMORY); 393 398 pUVM->u32Magic = UVM_MAGIC; 394 pUVM->cCpus = cC PUs;399 pUVM->cCpus = cCpus; 395 400 396 401 AssertCompile(sizeof(pUVM->vm.s) <= sizeof(pUVM->vm.padding)); … … 404 409 405 410 /* Initialize the VMCPU array in the UVM. */ 406 for (i = 0; i < cC PUs; i++)411 for (i = 0; i < cCpus; i++) 407 412 { 408 413 pUVM->aCpus[i].pUVM = pUVM; … … 416 421 { 417 422 /* Allocate a halt method event semaphore for each VCPU. */ 418 for (i = 0; i < cC PUs; i++)423 for (i = 0; i < cCpus; i++) 419 424 { 420 425 rc = RTSemEventCreate(&pUVM->aCpus[i].vm.s.EventSemWait); … … 440 445 * Start the emulation threads for all VMCPUs. 441 446 */ 442 for (i = 0; i < cC PUs; i++)447 for (i = 0; i < cCpus; i++) 443 448 { 444 449 rc = RTThreadCreate(&pUVM->aCpus[i].vm.s.ThreadEMT, vmR3EmulationThread, &pUVM->aCpus[i], _1M, … … 467 472 STAMR3TermUVM(pUVM); 468 473 } 469 for (i = 0; i < cC PUs; i++)474 for (i = 0; i < cCpus; i++) 470 475 { 471 476 RTSemEventDestroy(pUVM->aCpus[i].vm.s.EventSemWait); 477 pUVM->aCpus[i].vm.s.EventSemWait = NIL_RTSEMEVENT; 472 478 } 473 479 } … … 484 490 * @thread EMT 485 491 */ 486 static int vmR3CreateU(PUVM pUVM, uint32_t cC PUs, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM)492 static int vmR3CreateU(PUVM pUVM, uint32_t cCpus, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM) 487 493 { 488 494 int rc = VINF_SUCCESS; … … 510 516 CreateVMReq.pVMR0 = NIL_RTR0PTR; 511 517 CreateVMReq.pVMR3 = NULL; 512 CreateVMReq.cC PUs = cCPUs;518 CreateVMReq.cCpus = cCpus; 513 519 rc = SUPCallVMMR0Ex(NIL_RTR0PTR, 0 /* VCPU 0 */, VMMR0_DO_GVMM_CREATE_VM, 0, &CreateVMReq.Hdr); 514 520 if (RT_SUCCESS(rc)) … … 518 524 AssertRelease(pVM->pVMR0 == CreateVMReq.pVMR0); 519 525 AssertRelease(pVM->pSession == pUVM->vm.s.pSession); 520 AssertRelease(pVM->cCPUs == cC PUs);526 AssertRelease(pVM->cCPUs == cCpus); 521 527 AssertRelease(pVM->offVMCPU == RT_UOFFSETOF(VM, aCpus)); 522 528 … … 571 577 rc = CFGMR3QueryU32Def(CFGMR3GetRoot(pVM), "NumCPUs", &cCPUsCfg, 1); 572 578 AssertLogRelMsgRC(rc, ("Configuration error: Querying \"NumCPUs\" as integer failed, rc=%Rrc\n", rc)); 573 if (RT_SUCCESS(rc) && cCPUsCfg != cC PUs)579 if (RT_SUCCESS(rc) && cCPUsCfg != cCpus) 574 580 { 575 581 AssertLogRelMsgFailed(("Configuration error: \"NumCPUs\"=%RU32 and VMR3CreateVM::cCPUs=%RU32 does not match!\n", 576 cCPUsCfg, cC PUs));582 cCPUsCfg, cCpus)); 577 583 rc = VERR_INVALID_PARAMETER; 578 584 } … … 667 673 } 668 674 675 /** 676 * Register the calling EMT with GVM. 677 * 678 * @returns VBox status code. 679 * @param pVM The VM handle. 680 * @param idCpu The Virtual CPU ID. 681 */ 682 static DECLCALLBACK(int) vmR3RegisterEMT(PVM pVM, VMCPUID idCpu) 683 { 684 Assert(VMMGetCpuId(pVM) == idCpu); 685 int rc = SUPCallVMMR0Ex(pVM->pVMR0, idCpu, VMMR0_DO_GVMM_REGISTER_VMCPU, 0, NULL); 686 if (RT_FAILURE(rc)) 687 LogRel(("idCpu=%u rc=%Rrc\n", idCpu, rc)); 688 return rc; 689 } 690 669 691 670 692 /** … … 674 696 { 675 697 int rc; 698 699 /* 700 * Register the other EMTs with GVM. 701 */ 702 for (VMCPUID idCpu = 1; idCpu < pVM->cCPUs; idCpu++) 703 { 704 PVMREQ pReq; 705 rc = VMR3ReqCallU(pUVM, idCpu, &pReq, RT_INDEFINITE_WAIT, 0 /*fFlags*/, 706 (PFNRT)vmR3RegisterEMT, 2, pVM, idCpu); 707 if (RT_SUCCESS(rc)) 708 rc = pReq->iStatus; 709 VMR3ReqFree(pReq); 710 if (RT_FAILURE(rc)) 711 return rc; 712 } 676 713 677 714 /* -
trunk/src/VBox/VMM/VMEmt.cpp
r19300 r19395 44 44 #include <iprt/time.h> 45 45 46 47 /** 48 * The emulation thread. 46 /******************************************************************************* 47 * Internal Functions * 48 *******************************************************************************/ 49 int vmR3EmulationThreadWithId(RTTHREAD ThreadSelf, PUVMCPU pUVCpu, VMCPUID idCpu); 50 51 52 /** 53 * The emulation thread main function. 49 54 * 50 55 * @returns Thread exit code. 51 56 * @param ThreadSelf The handle to the executing thread. 52 * @param pvArgs Pointer to the user mode VM structure (UVM).57 * @param pvArgs Pointer to the user mode per-VCpu structure (UVMPCU). 53 58 */ 54 59 DECLCALLBACK(int) vmR3EmulationThread(RTTHREAD ThreadSelf, void *pvArgs) 55 60 { 56 61 PUVMCPU pUVCpu = (PUVMCPU)pvArgs; 57 PUVM pUVM = pUVCpu->pUVM; 58 RTCPUID idCpu = pUVCpu->idCpu; 62 return vmR3EmulationThreadWithId(ThreadSelf, pUVCpu, pUVCpu->idCpu); 63 } 64 65 66 /** 67 * The emulation thread main function, with Virtual CPU ID for debugging. 68 * 69 * @returns Thread exit code. 70 * @param ThreadSelf The handle to the executing thread. 71 * @param pUVCpu Pointer to the user mode per-VCpu structure. 72 * @param idCpu The virtual CPU ID, for backtrace purposes. 73 */ 74 int vmR3EmulationThreadWithId(RTTHREAD ThreadSelf, PUVMCPU pUVCpu, VMCPUID idCpu) 75 { 76 PUVM pUVM = pUVCpu->pUVM; 59 77 int rc; 60 78 … … 95 113 } 96 114 115 /* 116 * Only the first VCPU may initialize the VM during early init 117 * and must therefore service all VMCPUID_ANY requests. 118 * See also VMR3Create 119 */ 97 120 if ( pUVM->vm.s.pReqs 98 && pUVCpu->idCpu == 0 /* Only the first VCPU may initialize the VM during early init */)121 && pUVCpu->idCpu == 0) 99 122 { 100 123 /* 101 * Service execute in EMT request.124 * Service execute in any EMT request. 102 125 */ 103 126 rc = VMR3ReqProcessU(pUVM, VMCPUID_ANY); 104 127 Log(("vmR3EmulationThread: Req rc=%Rrc, VM state %d -> %d\n", rc, enmBefore, pUVM->pVM ? pUVM->pVM->enmVMState : VMSTATE_CREATING)); 105 128 } 106 else 107 if (pUVCpu->vm.s.pReqs) 129 else if (pUVCpu->vm.s.pReqs) 108 130 { 109 131 /* 110 * Service execute in EMT request.132 * Service execute in specific EMT request. 111 133 */ 112 134 rc = VMR3ReqProcessU(pUVM, pUVCpu->idCpu); … … 143 165 { 144 166 /* 145 * Service execute in EMT request.167 * Service execute in any EMT request. 146 168 */ 147 169 rc = VMR3ReqProcessU(pUVM, VMCPUID_ANY); … … 151 173 { 152 174 /* 153 * Service execute in EMT request.175 * Service execute in specific EMT request. 154 176 */ 155 177 rc = VMR3ReqProcessU(pUVM, pUVCpu->idCpu); … … 692 714 PVMCPU pVCpu = pUVCpu->pVCpu; 693 715 PVM pVM = pUVCpu->pVM; 716 Assert(VMMGetCpu(pVM) == pVCpu); 694 717 695 718 /* … … 775 798 PVM pVM = pUVCpu->pUVM->pVM; 776 799 PVMCPU pVCpu = VMMGetCpu(pVM); 800 Assert(pVCpu->idCpu == pUVCpu->idCpu); 777 801 778 802 int rc = VINF_SUCCESS; -
trunk/src/VBox/VMM/VMMAll/REMAll.cpp
r18927 r19395 58 58 { 59 59 /* Tell the recompiler to flush its TLB. */ 60 #ifndef DEBUG_bird /* temporary */ 60 61 Assert(pVM->cCPUs == 1); /* @todo SMP */ 62 #endif 61 63 CPUMSetChangedFlags(VMMGetCpu(pVM), CPUM_CHANGED_GLOBAL_TLB_FLUSH); 62 64 pVM->rem.s.cInvalidatedPages = 0; -
trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp
r19385 r19395 189 189 static DECLCALLBACK(void) gvmmR0HandleObjDestructor(void *pvObj, void *pvGVMM, void *pvHandle); 190 190 static int gvmmR0ByVM(PVM pVM, PGVM *ppGVM, PGVMM *ppGVMM, bool fTakeUsedLock); 191 static int gvmmR0ByVMAndEMT(PVM pVM, unsignedidCpu, PGVM *ppGVM, PGVMM *ppGVMM);191 static int gvmmR0ByVMAndEMT(PVM pVM, VMCPUID idCpu, PGVM *ppGVM, PGVMM *ppGVMM); 192 192 193 193 … … 486 486 pReq->pVMR0 = NULL; 487 487 pReq->pVMR3 = NIL_RTR3PTR; 488 int rc = GVMMR0CreateVM(pReq->pSession, pReq->cC PUs, &pVM);488 int rc = GVMMR0CreateVM(pReq->pSession, pReq->cCpus, &pVM); 489 489 if (RT_SUCCESS(rc)) 490 490 { … … 503 503 * @returns VBox status code. 504 504 * @param pSession The support driver session. 505 * @param cC PUs Number of virtual CPUs for the new VM.505 * @param cCpus Number of virtual CPUs for the new VM. 506 506 * @param ppVM Where to store the pointer to the VM structure. 507 507 * 508 508 * @thread EMT. 509 509 */ 510 GVMMR0DECL(int) GVMMR0CreateVM(PSUPDRVSESSION pSession, uint32_t cC PUs, PVM *ppVM)510 GVMMR0DECL(int) GVMMR0CreateVM(PSUPDRVSESSION pSession, uint32_t cCpus, PVM *ppVM) 511 511 { 512 512 LogFlow(("GVMMR0CreateVM: pSession=%p\n", pSession)); … … 517 517 *ppVM = NULL; 518 518 519 if ( cC PUs == 0520 || cC PUs > VMCPU_MAX_CPU_COUNT)519 if ( cCpus == 0 520 || cCpus > VMCPU_MAX_CPU_COUNT) 521 521 return VERR_INVALID_PARAMETER; 522 522 … … 571 571 * Allocate the global VM structure (GVM) and initialize it. 572 572 */ 573 PGVM pGVM = (PGVM)RTMemAllocZ(RT_UOFFSETOF(GVM, aCpus[cC PUs]));573 PGVM pGVM = (PGVM)RTMemAllocZ(RT_UOFFSETOF(GVM, aCpus[cCpus])); 574 574 if (pGVM) 575 575 { … … 577 577 pGVM->hSelf = iHandle; 578 578 pGVM->pVM = NULL; 579 pGVM->cC PUs = cCPUs;579 pGVM->cCpus = cCpus; 580 580 581 581 gvmmR0InitPerVMData(pGVM); … … 585 585 * Allocate the shared VM structure and associated page array. 586 586 */ 587 const uint32_t cbVM = RT_UOFFSETOF(VM, aCpus[cC PUs]);587 const uint32_t cbVM = RT_UOFFSETOF(VM, aCpus[cCpus]); 588 588 const uint32_t cPages = RT_ALIGN_32(cbVM, PAGE_SIZE) >> PAGE_SHIFT; 589 589 rc = RTR0MemObjAllocLow(&pGVM->gvmm.s.VMMemObj, cPages << PAGE_SHIFT, false /* fExecutable */); … … 597 597 pVM->hSelf = iHandle; 598 598 pVM->cbSelf = cbVM; 599 pVM->cCPUs = cC PUs;599 pVM->cCPUs = cCpus; 600 600 pVM->offVMCPU = RT_UOFFSETOF(VM, aCpus); 601 601 … … 622 622 623 623 /* Initialize all the VM pointers. */ 624 for (uint32_t i = 0; i < cC PUs; i++)624 for (uint32_t i = 0; i < cCpus; i++) 625 625 { 626 626 pVM->aCpus[i].pVMR0 = pVM; … … 709 709 pGVM->gvmm.s.fDoneVMMR0Term = false; 710 710 711 for ( unsigned i=0; i< pGVM->cCPUs; i++)711 for (VMCPUID i = 0; i < pGVM->cCpus; i++) 712 712 { 713 713 pGVM->aCpus[i].gvmm.s.HaltEventMulti = NIL_RTSEMEVENTMULTI; … … 732 732 PGVM pGVM; 733 733 PGVMM pGVMM; 734 int rc = gvmmR0ByVMAndEMT(pVM, 0 /* VCPU 0*/, &pGVM, &pGVMM);734 int rc = gvmmR0ByVMAndEMT(pVM, 0 /* idCpu */, &pGVM, &pGVMM); 735 735 if (RT_SUCCESS(rc)) 736 736 { … … 738 738 && pGVM->aCpus[0].gvmm.s.HaltEventMulti == NIL_RTSEMEVENTMULTI) 739 739 { 740 for ( unsigned i=0; i < pGVM->cCPUs; i++)740 for (VMCPUID i = 0; i < pGVM->cCpus; i++) 741 741 { 742 742 rc = RTSemEventMultiCreate(&pGVM->aCpus[i].gvmm.s.HaltEventMulti); … … 762 762 * 763 763 * @param pVM Pointer to the shared VM structure. 764 * @thread EMT(0) 764 765 */ 765 766 GVMMR0DECL(void) GVMMR0DoneInitVM(PVM pVM) … … 768 769 PGVM pGVM; 769 770 PGVMM pGVMM; 770 int rc = gvmmR0ByVMAndEMT(pVM, 0 /* VCPU 0*/, &pGVM, &pGVMM);771 int rc = gvmmR0ByVMAndEMT(pVM, 0 /* idCpu */, &pGVM, &pGVMM); 771 772 AssertRCReturnVoid(rc); 772 773 … … 782 783 * @param pVM Pointer to the shared VM structure. 783 784 * @param pGVM Pointer to the global VM structure. Optional. 785 * @thread EMT(0) 784 786 */ 785 787 GVMMR0DECL(bool) GVMMR0DoingTermVM(PVM pVM, PGVM pGVM) … … 791 793 { 792 794 PGVMM pGVMM; 793 int rc = gvmmR0ByVMAndEMT(pVM, 0 /* VCPU 0*/, &pGVM, &pGVMM);795 int rc = gvmmR0ByVMAndEMT(pVM, 0 /* idCpu */, &pGVM, &pGVMM); 794 796 AssertRCReturn(rc, false); 795 797 } … … 814 816 * @param pVM Where to store the pointer to the VM structure. 815 817 * 816 * @thread EMT if it's associated with the VM, otherwise any thread.818 * @thread EMT(0) if it's associated with the VM, otherwise any thread. 817 819 */ 818 820 GVMMR0DECL(int) GVMMR0DestroyVM(PVM pVM) … … 865 867 else 866 868 { 867 SUPR0Printf("GVMMR0DestroyVM: pHandle=%p:{.pVM=%p, hEMT =%p, .pvObj=%p} pVM=%p hSelf=%p\n",869 SUPR0Printf("GVMMR0DestroyVM: pHandle=%p:{.pVM=%p, hEMTCpu0=%p, .pvObj=%p} pVM=%p hSelf=%p\n", 868 870 pHandle, pHandle->pVM, pHandle->hEMTCpu0, pHandle->pvObj, pVM, hSelf); 869 871 gvmmR0CreateDestroyUnlock(pGVMM); … … 1019 1021 } 1020 1022 1021 for ( unsigned i=0; i< pGVM->cCPUs; i++)1023 for (VMCPUID i = 0; i < pGVM->cCpus; i++) 1022 1024 { 1023 1025 if (pGVM->aCpus[i].gvmm.s.HaltEventMulti != NIL_RTSEMEVENTMULTI) … … 1064 1066 * @param idCpu VCPU id. 1065 1067 */ 1066 GVMMR0DECL(int) GVMMR0RegisterVCpu(PVM pVM, unsignedidCpu)1068 GVMMR0DECL(int) GVMMR0RegisterVCpu(PVM pVM, VMCPUID idCpu) 1067 1069 { 1068 1070 AssertReturn(idCpu != 0, VERR_NOT_OWNER); … … 1216 1218 * @returns VBox status code. 1217 1219 * @param pVM The shared VM structure (the ring-0 mapping). 1218 * @param idCpu VCPU id1220 * @param idCpu The Virtual CPU ID of the calling EMT. 1219 1221 * @param ppGVM Where to store the GVM pointer. 1220 1222 * @param ppGVMM Where to store the pointer to the GVMM instance data. 1221 1223 * @thread EMT 1222 1224 * 1223 * @remark This will assert in failure paths.1224 */ 1225 static int gvmmR0ByVMAndEMT(PVM pVM, unsignedidCpu, PGVM *ppGVM, PGVMM *ppGVMM)1225 * @remark This will assert in all failure paths. 1226 */ 1227 static int gvmmR0ByVMAndEMT(PVM pVM, VMCPUID idCpu, PGVM *ppGVM, PGVMM *ppGVMM) 1226 1228 { 1227 1229 PGVMM pGVMM; … … 1242 1244 */ 1243 1245 PGVMHANDLE pHandle = &pGVMM->aHandles[hGVM]; 1244 RTNATIVETHREAD hAllegedEMT = RTThreadNativeSelf();1245 1246 AssertReturn(pHandle->pVM == pVM, VERR_NOT_OWNER); 1246 1247 AssertPtrReturn(pHandle->pvObj, VERR_INTERNAL_ERROR); … … 1249 1250 AssertPtrReturn(pGVM, VERR_INTERNAL_ERROR); 1250 1251 AssertReturn(pGVM->pVM == pVM, VERR_INTERNAL_ERROR); 1252 RTNATIVETHREAD hAllegedEMT = RTThreadNativeSelf(); 1253 AssertReturn(idCpu < pGVM->cCpus, VERR_INVALID_CPU_ID); 1254 #ifdef DEBUG_bird /* did bad stuff to my box just now, take it easy. */ 1255 if (RT_UNLIKELY(pGVM->aCpus[idCpu].hEMT != hAllegedEMT)) 1256 { 1257 SUPR0Printf("gvmmR0ByVMAndEMT: %x != %x idCpu=%u\n", pGVM->aCpus[idCpu].hEMT, hAllegedEMT, idCpu); 1258 return VERR_INTERNAL_ERROR; 1259 } 1260 #else 1251 1261 AssertReturn(pGVM->aCpus[idCpu].hEMT == hAllegedEMT, VERR_INTERNAL_ERROR); 1262 #endif 1252 1263 1253 1264 *ppGVM = pGVM; … … 1263 1274 * @returns VBox status code. 1264 1275 * @param pVM The shared VM structure (the ring-0 mapping). 1265 * @param idCpu VCPU id1276 * @param idCpu The Virtual CPU ID of the calling EMT. 1266 1277 * @param ppGVM Where to store the GVM pointer. 1267 1278 * @thread EMT 1268 1279 */ 1269 GVMMR0DECL(int) GVMMR0ByVMAndEMT(PVM pVM, unsignedidCpu, PGVM *ppGVM)1280 GVMMR0DECL(int) GVMMR0ByVMAndEMT(PVM pVM, VMCPUID idCpu, PGVM *ppGVM) 1270 1281 { 1271 1282 AssertPtrReturn(ppGVM, VERR_INVALID_POINTER); … … 1323 1334 && VALID_PTR(pGVMM->aHandles[i].pGVM)) 1324 1335 { 1336 if (pGVMM->aHandles[i].hEMTCpu0 == hEMT) 1337 return pGVMM->aHandles[i].pVM; 1338 1339 /** @todo this isn't safe as GVM may be deallocated while we're running. 1340 * Will change this to use RTPROCESS on the handle level as storing all the 1341 * thread handles there doesn't scale very well. */ 1325 1342 PGVM pGVM = pGVMM->aHandles[i].pGVM; 1326 1327 for (unsigned idCpu = 0; idCpu < pGVM->cCPUs; idCpu++) 1343 for (VMCPUID idCpu = 0; idCpu < pGVM->cCpus; idCpu++) 1328 1344 if (pGVM->aCpus[idCpu].hEMT == hEMT) 1329 1345 return pGVMM->aHandles[i].pVM; … … 1343 1359 static unsigned gvmmR0SchedDoWakeUps(PGVMM pGVMM, uint64_t u64Now) 1344 1360 { 1361 /** @todo Rewrite this algorithm. See performance defect XYZ. */ 1362 1345 1363 /* 1346 1364 * The first pass will wake up VMs which have actually expired … … 1359 1377 && pCurGVM->u32Magic == GVM_MAGIC) 1360 1378 { 1361 for ( unsigned idCpu = 0; idCpu < pCurGVM->cCPUs; idCpu++)1379 for (VMCPUID idCpu = 0; idCpu < pCurGVM->cCpus; idCpu++) 1362 1380 { 1363 1381 PGVMCPU pCurGVCpu = &pCurGVM->aCpus[idCpu]; … … 1399 1417 && pCurGVM->u32Magic == GVM_MAGIC) 1400 1418 { 1401 for ( unsigned idCpu = 0; idCpu < pCurGVM->cCPUs; idCpu++)1419 for (VMCPUID idCpu = 0; idCpu < pCurGVM->cCpus; idCpu++) 1402 1420 { 1403 1421 PGVMCPU pCurGVCpu = &pCurGVM->aCpus[idCpu]; … … 1429 1447 && pCurGVM->u32Magic == GVM_MAGIC) 1430 1448 { 1431 for ( unsigned idCpu = 0; idCpu < pCurGVM->cCPUs; idCpu++)1449 for (VMCPUID idCpu = 0; idCpu < pCurGVM->cCpus; idCpu++) 1432 1450 { 1433 1451 PGVMCPU pCurGVCpu = &pCurGVM->aCpus[idCpu]; … … 1459 1477 * VERR_INTERRUPTED if a signal was scheduled for the thread. 1460 1478 * @param pVM Pointer to the shared VM structure. 1461 * @param idCpu VCPU id1479 * @param idCpu The Virtual CPU ID of the calling EMT. 1462 1480 * @param u64ExpireGipTime The time for the sleep to expire expressed as GIP time. 1463 * @thread EMT .1464 */ 1465 GVMMR0DECL(int) GVMMR0SchedHalt(PVM pVM, unsignedidCpu, uint64_t u64ExpireGipTime)1481 * @thread EMT(idCpu). 1482 */ 1483 GVMMR0DECL(int) GVMMR0SchedHalt(PVM pVM, VMCPUID idCpu, uint64_t u64ExpireGipTime) 1466 1484 { 1467 1485 LogFlow(("GVMMR0SchedHalt: pVM=%p\n", pVM)); … … 1470 1488 * Validate the VM structure, state and handle. 1471 1489 */ 1472 PGVMM pGVMM; 1473 PGVM pGVM; 1474 PGVMCPU pCurGVCpu; 1475 1490 PGVM pGVM; 1491 PGVMM pGVMM; 1476 1492 int rc = gvmmR0ByVMAndEMT(pVM, idCpu, &pGVM, &pGVMM); 1477 1493 if (RT_FAILURE(rc)) 1478 1494 return rc; 1479 1480 1495 pGVM->gvmm.s.StatsSched.cHaltCalls++; 1481 1496 1482 pCurGVCpu = &pGVM->aCpus[idCpu];1483 Assert(idCpu < pGVM->cC PUs);1497 PGVMCPU pCurGVCpu = &pGVM->aCpus[idCpu]; 1498 Assert(idCpu < pGVM->cCpus); 1484 1499 Assert(!pCurGVCpu->gvmm.s.u64HaltExpire); 1485 1500 … … 1538 1553 * VINF_GVM_NOT_BLOCKED if the EMT thread wasn't blocked. 1539 1554 * @param pVM Pointer to the shared VM structure. 1540 * @param idCpu VCPU id1555 * @param idCpu The Virtual CPU ID of the EMT to wake up. 1541 1556 * @thread Any but EMT. 1542 1557 */ 1543 GVMMR0DECL(int) GVMMR0SchedWakeUp(PVM pVM, unsignedidCpu)1558 GVMMR0DECL(int) GVMMR0SchedWakeUp(PVM pVM, VMCPUID idCpu) 1544 1559 { 1545 1560 /* 1546 1561 * Validate input and take the UsedLock. 1547 1562 */ 1548 PGVMM pGVMM; 1549 PGVM pGVM; 1550 PGVMCPU pCurGVCpu; 1551 1563 PGVM pGVM; 1564 PGVMM pGVMM; 1552 1565 int rc = gvmmR0ByVM(pVM, &pGVM, &pGVMM, true /* fTakeUsedLock */); 1553 1566 if (RT_SUCCESS(rc)) 1554 1567 { 1555 Assert(idCpu < pGVM->cCPUs); 1556 1557 pCurGVCpu = &pGVM->aCpus[idCpu]; 1558 1559 pGVM->gvmm.s.StatsSched.cWakeUpCalls++; 1560 1561 /* 1562 * Signal the semaphore regardless of whether it's current blocked on it. 1563 * 1564 * The reason for this is that there is absolutely no way we can be 100% 1565 * certain that it isn't *about* go to go to sleep on it and just got 1566 * delayed a bit en route. So, we will always signal the semaphore when 1567 * the it is flagged as halted in the VMM. 1568 */ 1569 if (pCurGVCpu->gvmm.s.u64HaltExpire) 1570 { 1571 rc = VINF_SUCCESS; 1572 ASMAtomicXchgU64(&pCurGVCpu->gvmm.s.u64HaltExpire, 0); 1568 if (idCpu < pGVM->cCpus) 1569 { 1570 PGVMCPU pCurGVCpu = &pGVM->aCpus[idCpu]; 1571 pGVM->gvmm.s.StatsSched.cWakeUpCalls++; 1572 1573 /* 1574 * Signal the semaphore regardless of whether it's current blocked on it. 1575 * 1576 * The reason for this is that there is absolutely no way we can be 100% 1577 * certain that it isn't *about* go to go to sleep on it and just got 1578 * delayed a bit en route. So, we will always signal the semaphore when 1579 * the it is flagged as halted in the VMM. 1580 */ 1581 if (pCurGVCpu->gvmm.s.u64HaltExpire) 1582 { 1583 rc = VINF_SUCCESS; 1584 ASMAtomicXchgU64(&pCurGVCpu->gvmm.s.u64HaltExpire, 0); 1585 } 1586 else 1587 { 1588 rc = VINF_GVM_NOT_BLOCKED; 1589 pGVM->gvmm.s.StatsSched.cWakeUpNotHalted++; 1590 } 1591 1592 int rc2 = RTSemEventMultiSignal(pCurGVCpu->gvmm.s.HaltEventMulti); 1593 AssertRC(rc2); 1594 1595 /* 1596 * While we're here, do a round of scheduling. 1597 */ 1598 Assert(ASMGetFlags() & X86_EFL_IF); 1599 const uint64_t u64Now = RTTimeNanoTS(); /* (GIP time) */ 1600 pGVM->gvmm.s.StatsSched.cWakeUpWakeUps += gvmmR0SchedDoWakeUps(pGVMM, u64Now); 1601 1573 1602 } 1574 1603 else 1575 { 1576 rc = VINF_GVM_NOT_BLOCKED; 1577 pGVM->gvmm.s.StatsSched.cWakeUpNotHalted++; 1578 } 1579 1580 int rc2 = RTSemEventMultiSignal(pCurGVCpu->gvmm.s.HaltEventMulti); 1581 AssertRC(rc2); 1582 1583 /* 1584 * While we're here, do a round of scheduling. 1585 */ 1586 Assert(ASMGetFlags() & X86_EFL_IF); 1587 const uint64_t u64Now = RTTimeNanoTS(); /* (GIP time) */ 1588 pGVM->gvmm.s.StatsSched.cWakeUpWakeUps += gvmmR0SchedDoWakeUps(pGVMM, u64Now); 1589 1590 1591 rc2 = gvmmR0UsedUnlock(pGVMM); 1604 rc = VERR_INVALID_CPU_ID; 1605 1606 int rc2 = gvmmR0UsedUnlock(pGVMM); 1592 1607 AssertRC(rc2); 1593 1608 } … … 1607 1622 * VINF_GVM_YIELDED if an attempt to switch to a different VM task was made. 1608 1623 * @param pVM Pointer to the shared VM structure. 1609 * @param idCpu VCPU id1624 * @param idCpu The Virtual CPU ID of the calling EMT. 1610 1625 * @param u64ExpireGipTime The time for the sleep to expire expressed as GIP time. 1611 1626 * @param fYield Whether to yield or not. 1612 1627 * This is for when we're spinning in the halt loop. 1613 * @thread EMT .1614 */ 1615 GVMMR0DECL(int) GVMMR0SchedPoll(PVM pVM, unsignedidCpu, bool fYield)1628 * @thread EMT(idCpu). 1629 */ 1630 GVMMR0DECL(int) GVMMR0SchedPoll(PVM pVM, VMCPUID idCpu, bool fYield) 1616 1631 { 1617 1632 /* -
trunk/src/VBox/VMM/VMReq.cpp
r19366 r19395 262 262 VMMR3DECL(int) VMR3ReqCallVU(PUVM pUVM, VMCPUID idDstCpu, PVMREQ *ppReq, unsigned cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args) 263 263 { 264 LogFlow(("VMR3ReqCallV: cMillies=%d fFlags=%#x pfnFunction=%p cArgs=%d\n", cMillies, fFlags, pfnFunction, cArgs));264 LogFlow(("VMR3ReqCallV: idDstCpu=%u cMillies=%d fFlags=%#x pfnFunction=%p cArgs=%d\n", idDstCpu, cMillies, fFlags, pfnFunction, cArgs)); 265 265 266 266 /*
Note:
See TracChangeset
for help on using the changeset viewer.