Changeset 5033 in vbox
- Timestamp:
- Sep 26, 2007 4:48:51 AM (17 years ago)
- Location:
- trunk
- Files:
-
- 1 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/gmm.h
r5026 r5033 20 20 21 21 #include <VBox/types.h> 22 #include <VBox/gvmm.h> 22 23 23 #include "gvmm.h"24 24 25 25 /** @defgroup grp_gmm GMM - The Global Memory Manager … … 54 54 55 55 56 /** 57 * Over-commitment policy. 58 */ 59 typedef enum GMMOCPOLICY 60 { 61 /** The usual invalid 0 value. */ 62 GMMOCPOLICY_INVALID = 0, 63 /** No over-commitment, fully backed. 64 * The GMM guarantees that it will be able to allocate all of the 65 * guest RAM for a VM with OC policy. */ 66 GMMOCPOLICY_NO_OC, 67 /** to-be-determined. */ 68 GMMOCPOLICY_TBD, 69 /** The end of the valid policy range. */ 70 GMMOCPOLICY_END, 71 /** The usual 32-bit hack. */ 72 GMMOCPOLICY_32BIT_HACK = 0x7fffffff 73 } GMMOCPOLICY; 74 75 /** 76 * VM / Memory priority. 77 */ 78 typedef enum GMMPRORITY 79 { 80 /** The usual invalid 0 value. */ 81 GMMPRORITY_INVALID = 0, 82 /** High - avoid interrupting it if at all possible */ 83 GMMPRORITY_HIGH, 84 /** Normal - pause, save it or kill it. */ 85 GMMPRORITY_NORMAL, 86 /** Low - save or kill it. */ 87 GMMPRORITY_LOW, 88 /** The end of the valid priority range. */ 89 GMMPRORITY_END = 0, 90 /** The custom 32-bit type blowup. */ 91 GMMPRORITY_32BIT_HACK = 0x7fffffff 92 } GMMPRIORITY; 93 94 56 95 /** @} */ 57 96 -
trunk/src/VBox/VMM/Makefile.kmk
r5029 r5033 313 313 $(PATH_SUB_CURRENT) \ 314 314 PATM 315 VMMR0_DEFS = IN_VMM_R0 IN_RT_R0 IN_TRPM_R0 IN_CPUM_R0 IN_VM_R0 IN_TM_R0 IN_INTNET_R0 IN_HWACCM_R0 IN_EM_R0 IN_PDM_R0 IN_PGM_R0 IN_DIS_R0 IN_MM_R0 IN_SELM_R0 IN_CSAM_R0 IN_PATM_R0 IN_DBGF_R0 IN_REM_R0 IN_IOM_R0 IN_GVMM_R0 DIS_CORE_ONLY315 VMMR0_DEFS = IN_VMM_R0 IN_RT_R0 IN_TRPM_R0 IN_CPUM_R0 IN_VM_R0 IN_TM_R0 IN_INTNET_R0 IN_HWACCM_R0 IN_EM_R0 IN_PDM_R0 IN_PGM_R0 IN_DIS_R0 IN_MM_R0 IN_SELM_R0 IN_CSAM_R0 IN_PATM_R0 IN_DBGF_R0 IN_REM_R0 IN_IOM_R0 IN_GVMM_R0 IN_GMM_R0 DIS_CORE_ONLY 316 316 ifdef VBOX_WITH_IDT_PATCHING 317 317 VMMR0_DEFS += VBOX_WITH_IDT_PATCHING … … 327 327 VMMR0/CPUMR0.cpp \ 328 328 VMMR0/DBGFR0.cpp \ 329 VMMR0/GMMR0.cpp \ 329 330 VMMR0/GVMMR0.cpp \ 330 331 VMMR0/HWACCMR0.cpp \ … … 366 367 VMMAll/VMAll.cpp \ 367 368 369 368 370 ifeq ($(VBOX_LDR_FMT),pe) 369 371 VMMR0_SOURCES += VMMR0/VMMR0.def -
trunk/src/VBox/VMM/VMMR0/GMMR0.cpp
r5018 r5033 16 16 * 17 17 */ 18 18 19 19 20 /** @page pg_gmm GMM - The Global Memory Manager … … 140 141 * Header Files * 141 142 *******************************************************************************/ 142 #include "../PGMInternal.h" 143 143 #define LOG_GROUP LOG_GROUP_GMM 144 #include <VBox/gmm.h> 145 #include "GMMR0Internal.h" 146 #include <VBox/gvm.h> 147 #include <VBox/log.h> 148 #include <VBox/param.h> 149 #include <iprt/avl.h> 150 #include <iprt/mem.h> 151 #include <iprt/memobj.h> 152 #include <iprt/semaphore.h> 153 #include <iprt/string.h> 144 154 145 155 … … 155 165 * 156 166 * Because of the different layout on 32-bit and 64-bit hosts, macros 157 * are used to set and getthe data.167 * are used to get and set some of the data. 158 168 */ 159 169 typedef union GMMPAGE … … 347 357 uint16_t au16Reserved; 348 358 /** The pages. */ 349 GMMPAGE aPages[GMM_CHUNK_SIZE >> PAGE_S IZE];359 GMMPAGE aPages[GMM_CHUNK_SIZE >> PAGE_SHIFT]; 350 360 } GMMCHUNK; 351 361 … … 359 369 uint32_t idChunk; 360 370 /** Pointer to the chunk. */ 361 PG GMCHUNK pChunk;371 PGMMCHUNK pChunk; 362 372 } GMMCHUNKTLBE; 363 373 /** Pointer to an allocation chunk TLB entry. */ … … 415 425 * This is determined at initialization time. */ 416 426 bool fLegacyMode; 427 /** The number of active VMs. */ 428 uint16_t cActiveVMs; 417 429 } GMM; 418 430 /** Pointer to the GMM instance. */ … … 423 435 424 436 437 /******************************************************************************* 438 * Global Variables * 439 *******************************************************************************/ 440 /** Pointer to the GMM instance data. */ 441 static PGMM g_pGMM = NULL; 442 443 /** Macro for obtaining and validating the g_pGMM pointer. 444 * On failure it will return from the invoking function with the specified return value. 445 * 446 * @param pGMM The name of the pGMM variable. 447 * @param rc The return value on failure. Use VERR_INTERNAL_ERROR for 448 * VBox status codes. 449 */ 450 #define GMM_GET_VALID_INSTANCE(pGMM, rc) \ 451 do { \ 452 (pGMM) = g_pGMM; \ 453 AssertPtrReturn((pGMM), (rc)); \ 454 AssertMsgReturn((pGMM)->u32Magic == GMM_MAGIC, ("%p - %#x\n", (pGMM), (pGMM)->u32Magic), (rc)); \ 455 } while (0) 456 457 /** Macro for obtaining and validating the g_pGMM pointer, void function variant. 458 * On failure it will return from the invoking function. 459 * 460 * @param pGMM The name of the pGMM variable. 461 */ 462 #define GMM_GET_VALID_INSTANCE_VOID(pGMM) \ 463 do { \ 464 (pGMM) = g_pGMM; \ 465 AssertPtrReturnVoid((pGMM)); \ 466 AssertMsgReturnVoid((pGMM)->u32Magic == GMM_MAGIC, ("%p - %#x\n", (pGMM), (pGMM)->u32Magic)); \ 467 } while (0) 468 425 469 426 470 /******************************************************************************* 427 471 * Internal Functions * 428 472 *******************************************************************************/ 429 static DECLCALLBACK int gmmR0TermDestroyChunk(PAVLU32NODECORE pNode, void *pvGMM); 473 static DECLCALLBACK(int) gmmR0TermDestroyChunk(PAVLU32NODECORE pNode, void *pvGMM); 474 static DECLCALLBACK(int) gmmR0FreeVMPagesInChunk(PAVLU32NODECORE pNode, void *pvhGVM); 430 475 431 476 … … 507 552 g_pGMM = NULL; 508 553 pGMM->u32Magic++; 509 RTSem EventDestroy(&pGMM->Mtx);554 RTSemFastMutexDestroy(pGMM->Mtx); 510 555 pGMM->Mtx = NIL_RTSEMFASTMUTEX; 511 556 512 557 /* free any chunks still hanging around. */ 513 RTAvlU32Destroy( pGMM->Chunks, gmmR0TermDestroyChunk, pGMM);558 RTAvlU32Destroy(&pGMM->pChunks, gmmR0TermDestroyChunk, pGMM); 514 559 515 560 /* finally the instance data itself. */ … … 526 571 * @param pvGMM The GMM handle. 527 572 */ 528 static DECLCALLBACK intgmmR0TermDestroyChunk(PAVLU32NODECORE pNode, void *pvGMM)529 { 530 PGMMCHUNK pChunk = (PGMMCHUNK) 573 static DECLCALLBACK(int) gmmR0TermDestroyChunk(PAVLU32NODECORE pNode, void *pvGMM) 574 { 575 PGMMCHUNK pChunk = (PGMMCHUNK)pNode; 531 576 532 577 if (pChunk->cFree != (GMM_CHUNK_SIZE >> PAGE_SHIFT)) … … 553 598 554 599 /** 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; 600 * Initializes the per-VM data for the GMM. 601 * 602 * @param pGVM Pointer to the Global VM structure. 603 */ 604 GMMR0DECL(void) GMMR0InitPerVMData(PGVM pGVM) 605 { 606 pGVM->gmm.s.cRAMPages = 0; 607 pGVM->gmm.s.cPrivatePages = 0; 608 pGVM->gmm.s.cSharedPages = 0; 609 pGVM->gmm.s.enmPolicy = GMMOCPOLICY_TBD; 610 pGVM->gmm.s.enmPriority = GMMPRORITY_NORMAL; 611 } 612 613 614 /** 615 * Cleans up when a VM is terminating. 616 * 617 * @param pGVM Pointer to the Global VM structure. 618 */ 619 GMMR0DECL(void) GMMR0CleanupVM(PGVM pGVM) 620 { 621 LogFlow(("GMMR0CleanupVM: pGVM=%p:{.pVM=%p, .hSelf=%#x}\n", pGVM, pGVM->pVM, pGVM->hSelf)); 622 623 PGMM pGMM; 624 GMM_GET_VALID_INSTANCE_VOID(pGMM); 568 625 569 626 int rc = RTSemFastMutexRequest(pGMM->Mtx); … … 571 628 572 629 /* 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. 630 * If it's the last VM around, we can skip walking all the chunk looking 631 * for the pages owned by this VM and instead flush the whole shebang. 632 * 633 * This takes care of the eventuality that a VM has left shared page 634 * references behind (shouldn't happen of course, but you never know). 576 635 */ 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 636 if (pGMM->cActiveVMs == 1) 637 { 638 639 } 640 else if (pGVM->gmm.s.cPrivatePages) 641 { 642 /* 643 * Walk the entire pool looking for pages that belongs to this VM. 644 * This is slow but necessary. Of course it won't work for shared 645 * pages, but we'll deal with that later. 646 */ 647 RTAvlU32DoWithAll(&pGMM->pChunks, true /* fFromLeft */, gmmR0FreeVMPagesInChunk, (void *)pGVM->hSelf); 648 649 /* 650 * Update over-commitment management and free chunks that are no 651 * longer needed. 652 */ 653 654 } 584 655 585 656 RTSemFastMutexRelease(pGMM->Mtx); 657 658 /* trash the data */ 659 pGVM->gmm.s.cRAMPages = 0; 660 pGVM->gmm.s.cPrivatePages = 0; 661 pGVM->gmm.s.cSharedPages = 0; 662 pGVM->gmm.s.enmPolicy = GMMOCPOLICY_INVALID; 663 pGVM->gmm.s.enmPriority = GMMPRORITY_INVALID; 664 586 665 LogFlow(("GMMR0CleanupVM: returns\n")); 587 666 } 588 667 589 668 669 /** 670 * RTAvlU32DoWithAll callback. 671 * 672 * @returns 0 673 * @param pNode The node to destroy. 674 * @param pvhGVM The GVM::hSelf value. 675 */ 676 static DECLCALLBACK(int) gmmR0FreeVMPagesInChunk(PAVLU32NODECORE pNode, void *pvhGVM) 677 { 678 PGMMCHUNK pChunk = (PGMMCHUNK)pNode; 679 uint16_t hGVM = (uintptr_t)pvhGVM; 680 681 #ifndef VBOx_STRICT 682 if (pChunk->cFree != (GMM_CHUNK_SIZE >> PAGE_SHIFT)) 683 #endif 684 { 685 /* 686 * Perform some internal checks while we're scanning. 687 */ 688 unsigned cPrivate = 0; 689 unsigned cShared = 0; 690 unsigned cFree = 0; 691 692 unsigned iPage = (GMM_CHUNK_SIZE >> PAGE_SHIFT); 693 while (iPage-- > 0) 694 if (GMM_PAGE_IS_PRIVATE(&pChunk->aPages[iPage])) 695 696 { 697 if (pChunk->aPages[iPage].Private.hGVM == hGVM) 698 { 699 /* Free it. */ 700 pChunk->aPages[iPage].u = 0; 701 pChunk->aPages[iPage].Free.idNext = pChunk->idFreeHead; 702 pChunk->aPages[iPage].Free.u2State = GMM_PAGE_STATE_FREE; 703 pChunk->idFreeHead = iPage; 704 pChunk->cPrivate--; 705 pChunk->cFree++; 706 cFree++; 707 } 708 else 709 cPrivate++; 710 } 711 else if (GMM_PAGE_IS_FREE(&pChunk->aPages[iPage])) 712 cFree++; 713 else 714 cShared++; 715 716 /* 717 * Did it add up? 718 */ 719 if (RT_UNLIKELY( pChunk->cFree != cFree 720 || pChunk->cPrivate != cPrivate 721 || pChunk->cShared != cShared)) 722 { 723 SUPR0Printf("GMM: Chunk %p/%#x has bogus stats - free=%d/%d private=%d/%d shared=%d/%d\n", 724 pChunk->cFree, cFree, pChunk->cPrivate, cPrivate, pChunk->cShared, cShared); 725 pChunk->cFree = cFree; 726 pChunk->cPrivate = cPrivate; 727 pChunk->cShared = cShared; 728 } 729 } 730 731 return 0; 732 } 733 734 735
Note:
See TracChangeset
for help on using the changeset viewer.