- Timestamp:
- Sep 24, 2007 10:24:07 PM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR0/GMMR0.cpp
r5017 r5018 178 178 uint32_t pfn; 179 179 /** The GVM handle. (64K VMs) */ 180 uint32_t iGVM : 16;180 uint32_t hGVM : 16; 181 181 /** Reserved. */ 182 182 uint32_t u16Reserved : 14; … … 190 190 /** The reference count. */ 191 191 uint32_t cRefs; 192 /** Reserved. Checksum or something? Two iGVMs for forking? */192 /** Reserved. Checksum or something? Two hGVMs for forking? */ 193 193 uint32_t u30Reserved : 30; 194 194 /** The page state. */ … … 222 222 uint32_t pfn : 24; 223 223 /** The GVM handle. (127 VMs) */ 224 uint32_t iGVM : 7;224 uint32_t hGVM : 7; 225 225 /** The top page state bit, MBZ. */ 226 226 uint32_t fZero : 1; … … 339 339 * is used as a preference when there are several chunks to choose from. 340 340 * When in legacy mode this isn't a preference any longer. */ 341 uint16_t iGVM;341 uint16_t hGVM; 342 342 /** The number of private pages. */ 343 343 uint16_t cPrivate; … … 396 396 typedef struct GMM 397 397 { 398 /** Magic / eye catcher. GMM_MAGIC */ 399 uint32_t u32Magic; 398 400 /** The fast mutex protecting the GMM. 399 401 * More fine grained locking can be implemented later if necessary. */ … … 417 419 typedef GMM *PGMM; 418 420 419 421 /** The value of GMM::u32Magic (Katsuhiro Otomo). */ 422 #define GMM_MAGIC 0x19540414 423 424 425 426 /******************************************************************************* 427 * Internal Functions * 428 *******************************************************************************/ 429 static DECLCALLBACK int gmmR0TermDestroyChunk(PAVLU32NODECORE pNode, void *pvGMM); 430 431 432 433 /** 434 * Initializes the GMM component. 435 * 436 * This is called when the VMMR0.r0 module is loaded and protected by the 437 * loader semaphore. 438 * 439 * @returns VBox status code. 440 */ 441 GMMR0DECL(int) GMMR0Init(void) 442 { 443 LogFlow(("GMMInit:\n")); 444 445 /* 446 * Allocate the instance data and the lock(s). 447 */ 448 PGMM pGMM = (PGMM)RTMemAllocZ(sizeof(*pGMM)); 449 if (!pGMM) 450 return VERR_NO_MEMORY; 451 pGMM->u32Magic = GMM_MAGIC; 452 for (unsigned i = 0; i < RT_ELEMENTS(pGMM->ChunkTLB.aEntries); i++) 453 pGMM->ChunkTLB.aEntries[i].idChunk = NIL_GMM_CHUNKID; 454 455 int rc = RTSemFastMutexCreate(&pGMM->Mtx); 456 if (RT_SUCCESS(rc)) 457 { 458 /* 459 * Check and see if RTR0MemObjAllocPhysNC works. 460 */ 461 RTR0MEMOBJ MemObj; 462 rc = RTR0MemObjAllocPhysNC(&MemObj, _64K, NIL_RTHCPHYS); 463 if (RT_SUCCESS(rc)) 464 { 465 rc = RTR0MemObjFree(MemObj, true); 466 AssertRC(rc); 467 } 468 else if (rc == VERR_NOT_SUPPORTED) 469 pGMM->fLegacyMode = true; 470 else 471 SUPR0Printf("GMMR0Init: RTR0MemObjAllocPhysNC(,64K,Any) -> %d!\n", rc); 472 473 g_pGMM = pGMM; 474 LogFlow(("GMMInit: pGMM=%p fLegacy=%RTbool\n", pGMM, pGMM->fLegacyMode)); 475 return VINF_SUCCESS; 476 } 477 478 RTMemFree(pGMM); 479 SUPR0Printf("GMMR0Init: failed! rc=%d\n", rc); 480 return rc; 481 } 482 483 484 /** 485 * Terminates the GMM component. 486 */ 487 GMMR0DECL(void) GMMR0Term(void) 488 { 489 LogFlow(("GMMTerm:\n")); 490 491 /* 492 * Take care / be paranoid... 493 */ 494 PGMM pGMM = g_pGMM; 495 if (!VALID_PTR(pGMM)) 496 return; 497 if (pGMM->u32Magic != GMM_MAGIC) 498 { 499 SUPR0Printf("GMMR0Term: u32Magic=%#x\n", pGMM->u32Magic); 500 return; 501 } 502 503 /* 504 * Undo what init did and free any resources we've acquired. 505 */ 506 /* Destroy the fundamentals. */ 507 g_pGMM = NULL; 508 pGMM->u32Magic++; 509 RTSemEventDestroy(&pGMM->Mtx); 510 pGMM->Mtx = NIL_RTSEMFASTMUTEX; 511 512 /* free any chunks still hanging around. */ 513 RTAvlU32Destroy(pGMM->Chunks, gmmR0TermDestroyChunk, pGMM); 514 515 /* finally the instance data itself. */ 516 RTMemFree(pGMM); 517 LogFlow(("GMMTerm: done\n")); 518 } 519 520 521 /** 522 * RTAvlU32Destroy callback. 523 * 524 * @returns 0 525 * @param pNode The node to destroy. 526 * @param pvGMM The GMM handle. 527 */ 528 static DECLCALLBACK int gmmR0TermDestroyChunk(PAVLU32NODECORE pNode, void *pvGMM) 529 { 530 PGMMCHUNK pChunk = (PGMMCHUNK) pNode; 531 532 if (pChunk->cFree != (GMM_CHUNK_SIZE >> PAGE_SHIFT)) 533 SUPR0Printf("GMMR0Term: %p/%#x: cFree=%d cPrivate=%d cShared=%d cMappings=%d\n", pChunk, 534 pChunk->Core.Key, pChunk->cFree, pChunk->cPrivate, pChunk->cShared, pChunk->cMappings); 535 536 int rc = RTR0MemObjFree(pChunk->MemObj, true /* fFreeMappings */); 537 if (RT_FAILURE(rc)) 538 { 539 SUPR0Printf("GMMR0Term: %p/%#x: RTRMemObjFree(%p,true) -> %d (cMappings=%d)\n", pChunk, 540 pChunk->Core.Key, pChunk->MemObj, rc, pChunk->cMappings); 541 AssertRC(rc); 542 } 543 pChunk->MemObj = NIL_RTR0MEMOBJ; 544 545 RTMemFree(pChunk->paMappings); 546 pChunk->paMappings = NULL; 547 548 RTMemFree(pChunk); 549 NOREF(pvGMM); 550 return 0; 551 } 552 553 554 /** 555 * Cleans up when a VM is terminated. 556 * 557 * @param pVM The VM structure. 558 * @param hGVM The global VM handle. 559 */ 560 GMMR0DECL(void) GMMR0CleanupVM(PVM pVM, uint32_t hGVM) 561 { 562 LogFlow(("GMMR0CleanupVM: pVM=%p hGVM=%#x\n", pVM, hGVM)); 563 564 PGMM pGMM = g_pGMM; 565 if ( !VALID_PTR(pGMM) 566 || pGMM->u32Magic != GMM_MAGIC) 567 return; 568 569 int rc = RTSemFastMutexRequest(pGMM->Mtx); 570 AssertRC(rc); 571 572 /* 573 * Walk the entire pool looking for pages that belongs to this VM. 574 * This is slow but necessary. Of course it won't work for shared 575 * pages, but we'll deal with that later. 576 */ 577 578 579 /* 580 * Update over-commitment management and free chunks that are no 581 * longer needed. If no VMs are around, free everything. 582 */ 583 584 585 RTSemFastMutexRelease(pGMM->Mtx); 586 LogFlow(("GMMR0CleanupVM: returns\n")); 587 } 588 589
Note:
See TracChangeset
for help on using the changeset viewer.