VirtualBox

Changeset 13543 in vbox for trunk/src


Ignore:
Timestamp:
Oct 23, 2008 4:49:58 PM (16 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
38400
Message:

#1865: PGMPool.

Location:
trunk/src/VBox/VMM
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/PGMPool.cpp

    r13135 r13543  
    2626 *         should allow us to skip most of the global flushes now following access
    2727 *         handler changes. The main expense is flushing shadow pages.
    28  *      -# Limit the pool size (currently it's kind of limitless IIRC).
    29  *      -# Allocate shadow pages from GC. Currently we're allocating at SyncCR3 time.
     28 *      -# Limit the pool size if necessary (default is kind of limitless).
     29 *      -# Allocate shadow pages from RC. We use to only do this in SyncCR3.
    3030 *      -# Required for 64-bit guests.
    3131 *      -# Combining the PD cache and page pool in order to simplify caching.
     
    3434 * @section sec_pgm_pool_outline    Design Outline
    3535 *
    36  * The shadow page pool tracks pages used for shadowing paging structures (i.e. page
    37  * tables, page directory, page directory pointer table and page map level-4). Each
    38  * page in the pool has an unique identifier. This identifier is used to link a guest
    39  * physical page to a shadow PT. The identifier is a non-zero value and has a
    40  * relativly low max value - say 14 bits. This makes it possible to fit it into the
    41  * upper bits of the of the aHCPhys entries in the ram range.
    42  *
    43  * By restricting host physical memory to the first 48 bits (which is the announced
    44  * physical memory range of the K8L chip (scheduled for 2008)), we can safely use the
    45  * upper 16 bits for shadow page ID and reference counting.
    46  *
    47  * Now, it's possible for a page to be aliased, i.e. mapped by more than one PT or
    48  * PD. This is solved by creating a list of physical cross reference extents when
    49  * ever this happens. Each node in the list (extent) is can contain 3 page pool
    50  * indexes. The list it self is chained using indexes into the paPhysExt array.
     36 * The shadow page pool tracks pages used for shadowing paging structures (i.e.
     37 * page tables, page directory, page directory pointer table and page map
     38 * level-4). Each page in the pool has an unique identifier. This identifier is
     39 * used to link a guest physical page to a shadow PT. The identifier is a
     40 * non-zero value and has a relativly low max value - say 14 bits. This makes it
     41 * possible to fit it into the upper bits of the of the aHCPhys entries in the
     42 * ram range.
     43 *
     44 * By restricting host physical memory to the first 48 bits (which is the
     45 * announced physical memory range of the K8L chip (scheduled for 2008)), we
     46 * can safely use the upper 16 bits for shadow page ID and reference counting.
     47 *
     48 * Update: The 48 bit assumption will be lifted with the new physical memory
     49 * management (PGMPAGE), so we won't have any trouble when someone stuffs 2TB
     50 * into a box in some years.
     51 *
     52 * Now, it's possible for a page to be aliased, i.e. mapped by more than one PT
     53 * or PD. This is solved by creating a list of physical cross reference extents
     54 * when ever this happens. Each node in the list (extent) is can contain 3 page
     55 * pool indexes. The list it self is chained using indexes into the paPhysExt
     56 * array.
    5157 *
    5258 *
     
    7884 * @section sec_pgm_pool_impl       Implementation
    7985 *
    80  * The pool will take pages from the MM page pool. The tracking data (attributes,
    81  * bitmaps and so on) are allocated from the hypervisor heap. The pool content can
    82  * be accessed both by using the page id and the physical address (HC). The former
    83  * is managed by means of an array, the latter by an offset based AVL tree.
     86 * The pool will take pages from the MM page pool. The tracking data
     87 * (attributes, bitmaps and so on) are allocated from the hypervisor heap. The
     88 * pool content can be accessed both by using the page id and the physical
     89 * address (HC). The former is managed by means of an array, the latter by an
     90 * offset based AVL tree.
    8491 *
    8592 * Flushing of a pool page means that we iterate the content (we know what kind
     
    125132     */
    126133    PCFGMNODE pCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "/PGM/Pool");
     134
     135    /** @cfgm{/PGM/Pool/MaxPages, uint16_t, #pages, 16, 0x3fff, 1024}
     136     * The max size of the shadow page pool in pages. The pool will grow dynamically
     137     * up to this limit.
     138     */
    127139    uint16_t cMaxPages;
    128     int rc = CFGMR3QueryU16(pCfg, "MaxPages", &cMaxPages);
    129     if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
    130         cMaxPages = 4*_1M >> PAGE_SHIFT;
    131     else if (VBOX_FAILURE(rc))
    132         AssertRCReturn(rc, rc);
    133     else
    134         AssertMsgReturn(cMaxPages <= PGMPOOL_IDX_LAST && cMaxPages >= RT_ALIGN(PGMPOOL_IDX_FIRST, 16),
    135                         ("cMaxPages=%u (%#x)\n", cMaxPages, cMaxPages), VERR_INVALID_PARAMETER);
     140    int rc = CFGMR3QueryU16Def(pCfg, "MaxPages", &cMaxPages, 4*_1M >> PAGE_SHIFT);
     141    AssertLogRelRCReturn(rc, rc);
     142    AssertLogRelMsgReturn(cMaxPages <= PGMPOOL_IDX_LAST && cMaxPages >= RT_ALIGN(PGMPOOL_IDX_FIRST, 16),
     143                          ("cMaxPages=%u (%#x)\n", cMaxPages, cMaxPages), VERR_INVALID_PARAMETER);
    136144    cMaxPages = RT_ALIGN(cMaxPages, 16);
    137145
     146    /** @cfgm{/PGM/Pool/MaxUsers, uint16_t, #users, MaxUsers, 32K, MaxPages*2}
     147     * The max number of shadow page user tracking records. Each shadow page has
     148     * zero of other shadow pages (or CR3s) that references it, or uses it if you
     149     * like. The structures describing these relationships are allocated from a
     150     * fixed sized pool. This configuration variable defines the pool size.
     151     */
    138152    uint16_t cMaxUsers;
    139     rc = CFGMR3QueryU16(pCfg, "MaxUsers", &cMaxUsers);
    140     if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
    141         cMaxUsers = cMaxPages * 2;
    142     else if (VBOX_FAILURE(rc))
    143         AssertRCReturn(rc, rc);
    144     else
    145         AssertMsgReturn(cMaxUsers >= cMaxPages && cMaxPages <= _32K,
    146                         ("cMaxUsers=%u (%#x)\n", cMaxUsers, cMaxUsers), VERR_INVALID_PARAMETER);
    147 
     153    rc = CFGMR3QueryU16Def(pCfg, "MaxUsers", &cMaxUsers, cMaxPages * 2);
     154    AssertLogRelRCReturn(rc, rc);
     155    AssertLogRelMsgReturn(cMaxUsers >= cMaxPages && cMaxPages <= _32K,
     156                          ("cMaxUsers=%u (%#x)\n", cMaxUsers, cMaxUsers), VERR_INVALID_PARAMETER);
     157
     158    /** @cfgm{/PGM/Pool/MaxPhysExts, uint16_t, #extents, 16, MaxPages * 2, MAX(MaxPages*2,0x3fff)}
     159     * The max number of extents for tracking aliased guest pages.
     160     */
    148161    uint16_t cMaxPhysExts;
    149     rc = CFGMR3QueryU16(pCfg, "MaxPhysExts", &cMaxPhysExts);
    150     if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
    151         cMaxPhysExts = RT_MAX(cMaxPages * 2, PGMPOOL_IDX_LAST);
    152     else if (VBOX_FAILURE(rc))
    153         AssertRCReturn(rc, rc);
    154     else
    155         AssertMsgReturn(cMaxPhysExts >= 16 && cMaxPages <= PGMPOOL_IDX_LAST,
    156                         ("cMaxPhysExts=%u (%#x)\n", cMaxPhysExts, cMaxUsers), VERR_INVALID_PARAMETER);
    157 
     162    rc = CFGMR3QueryU16Def(pCfg, "MaxPhysExts", &cMaxPhysExts, RT_MAX(cMaxPages * 2, PGMPOOL_IDX_LAST));
     163    AssertLogRelRCReturn(rc, rc);
     164    AssertLogRelMsgReturn(cMaxPhysExts >= 16 && cMaxPages <= PGMPOOL_IDX_LAST,
     165                          ("cMaxPhysExts=%u (%#x)\n", cMaxPhysExts, cMaxPhysExts), VERR_INVALID_PARAMETER);
     166
     167    /** @cfgm{/PGM/Pool/ChacheEnabled, bool, true}
     168     * Enables or disabling caching of shadow pages. Chaching means that we will try
     169     * reuse shadow pages instead of recreating them everything SyncCR3, SyncPT or
     170     * SyncPage requests one. When reusing a shadow page, we can save time
     171     * reconstructing it and it's children.
     172     */
    158173    bool fCacheEnabled;
    159     rc = CFGMR3QueryBool(pCfg, "CacheEnabled", &fCacheEnabled);
    160     if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
    161         fCacheEnabled = true;
    162     else if (VBOX_FAILURE(rc))
    163         AssertRCReturn(rc, rc);
     174    rc = CFGMR3QueryBoolDef(pCfg, "CacheEnabled", &fCacheEnabled, true);
     175    AssertLogRelRCReturn(rc, rc);
    164176
    165177    Log(("pgmR3PoolInit: cMaxPages=%#RX16 cMaxUsers=%#RX16 cMaxPhysExts=%#RX16 fCacheEnable=%RTbool\n",
  • trunk/src/VBox/VMM/VMMAll/PGMAllPool.cpp

    r13202 r13543  
    475475                }
    476476#ifdef PGMPOOL_INVALIDATE_UPPER_SHADOW_TABLE_ENTRIES
    477                 /* causes trouble when the guest uses a PDE to refer to the whole page table level structure. (invalidate here; faults later on when it tries
    478                  * to change the page table entries
    479                  * -> recheck; probably only applies to the GC case
     477                /*
     478                 * Causes trouble when the guest uses a PDE to refer to the whole page table level
     479                 * structure. (Invalidate here; faults later on when it tries to change the page
     480                 * table entries -> recheck; probably only applies to the RC case.)
    480481                 */
    481482                else
     
    509510                    }
    510511#ifdef PGMPOOL_INVALIDATE_UPPER_SHADOW_TABLE_ENTRIES
    511                     else
    512                     if (uShw.pPDPae->a[iShw2].n.u1Present)
     512                    else if (uShw.pPDPae->a[iShw2].n.u1Present)
    513513                    {
    514514                        LogFlow(("pgmPoolMonitorChainChanging: pae pd iShw2=%#x: %RX64 -> freeing it!\n", iShw2, uShw.pPDPae->a[iShw2].u));
     
    527527            case PGMPOOLKIND_ROOT_PDPT:
    528528            {
    529                 /* Hopefully this doesn't happen very often:
     529                /*
     530                 * Hopefully this doesn't happen very often:
    530531                 * - touching unused parts of the page
    531532                 * - messing with the bits of pd pointers without changing the physical address
     
    614615            case PGMPOOLKIND_64BIT_PDPT_FOR_64BIT_PDPT:
    615616            {
    616                 /* Hopefully this doesn't happen very often:
     617                /*
     618                 * Hopefully this doesn't happen very often:
    617619                 * - messing with the bits of pd pointers without changing the physical address
    618620                 */
     
    645647            case PGMPOOLKIND_64BIT_PML4_FOR_64BIT_PML4:
    646648            {
    647                 /* Hopefully this doesn't happen very often:
     649                /*
     650                 * Hopefully this doesn't happen very often:
    648651                 * - messing with the bits of pd pointers without changing the physical address
    649652                 */
     
    744747{
    745748#ifndef IN_GC
     749    /** @todo could make this general, faulting close to rsp should be safe reuse heuristic. */
    746750    if (   HWACCMHasPendingIrq(pVM)
    747751        && (pRegFrame->rsp - pvFault) < 32)
     
    752756    }
    753757#else
    754     NOREF(pVM);
     758    NOREF(pVM); NOREF(pvFault);
    755759#endif
    756760
     
    10731077#endif  /* PGMPOOL_WITH_MONITORING */
    10741078
    1075 
    1076 
    10771079#ifdef PGMPOOL_WITH_CACHE
     1080
    10781081/**
    10791082 * Inserts a page into the GCPhys hash table.
     
    14141417    pPage->iAgePrev = NIL_PGMPOOL_IDX;
    14151418}
     1419
    14161420#endif /* PGMPOOL_WITH_CACHE */
    1417 
    1418 
    14191421#ifdef PGMPOOL_WITH_MONITORING
     1422
    14201423/**
    14211424 * Looks for pages sharing the monitor.
     
    14901493}
    14911494
     1495
    14921496/**
    14931497 * Enabled write monitoring of a guest page.
     
    16801684}
    16811685
    1682 
    1683 #ifdef PGMPOOL_WITH_MIXED_PT_CR3
     1686# ifdef PGMPOOL_WITH_MIXED_PT_CR3
     1687
    16841688/**
    16851689 * Set or clear the fCR3Mix attribute in a chain of monitored pages.
     
    18001804    return rc;
    18011805}
    1802 #endif /* PGMPOOL_WITH_MIXED_PT_CR3 */
    1803 
     1806
     1807# endif /* PGMPOOL_WITH_MIXED_PT_CR3 */
    18041808
    18051809/**
     
    20182022}
    20192023
     2024
    20202025/**
    20212026 * Handle SyncCR3 pool tasks
     
    20512056    return VINF_SUCCESS;
    20522057}
     2058
    20532059#endif /* PGMPOOL_WITH_MONITORING */
    2054 
    20552060#ifdef PGMPOOL_WITH_USER_TRACKING
     2061
    20562062/**
    20572063 * Frees up at least one user entry.
     
    24022408}
    24032409
    2404 
    24052410#ifdef PGMPOOL_WITH_GCPHYS_TRACKING
     2411
    24062412/**
    24072413 * Scans one shadow page table for mappings of a physical page.
     
    25752581    STAM_PROFILE_STOP(&pPool->StatTrackFlushGCPhysPTs, f);
    25762582}
     2583
    25772584#endif /* PGMPOOL_WITH_GCPHYS_TRACKING */
    2578 
    25792585
    25802586/**
     
    28192825}
    28202826
    2821 
    28222827#ifdef PGMPOOL_WITH_GCPHYS_TRACKING
     2828
    28232829/**
    28242830 * Allocates a new physical cross reference extent.
     
    28892895    pPool->iPhysExtFreeHead = iPhysExtStart;
    28902896}
     2897
    28912898
    28922899/**
     
    30763083
    30773084
    3078 
    30793085/**
    30803086 * Clear references to guest physical memory.
     
    31033109            const unsigned iPage = off >> PAGE_SHIFT;
    31043110            Assert(PGM_PAGE_GET_HCPHYS(&pRam->aPages[iPage]));
     3111#ifdef LOG_ENABLED
    31053112RTHCPHYS HCPhysPage = PGM_PAGE_GET_HCPHYS(&pRam->aPages[iPage]);
    31063113Log(("pgmPoolTracDerefGCPhys %VHp vs %VHp\n", HCPhysPage, HCPhys));
     3114#endif
    31073115            if (PGM_PAGE_GET_HCPHYS(&pRam->aPages[iPage]) == HCPhys)
    31083116            {
     
    32753283        }
    32763284}
     3285
    32773286#endif /* PGMPOOL_WITH_GCPHYS_TRACKING */
    3278 
    32793287
    32803288/**
     
    33253333}
    33263334
     3335
    33273336/**
    33283337 * Clear references to shadowed pages in a 64-bit level 4 page table.
     
    33483357}
    33493358
     3359
    33503360/**
    33513361 * Clear references to shadowed pages in an EPT page table.
     
    33663376        }
    33673377}
     3378
    33683379
    33693380/**
     
    33903401}
    33913402
     3403
    33923404/**
    33933405 * Clear references to shadowed pages in an EPT page directory pointer table.
     
    34123424    }
    34133425}
     3426
    34143427
    34153428/**
     
    35293542    pPage->fZeroed = true;
    35303543}
     3544
    35313545#endif /* PGMPOOL_WITH_USER_TRACKING */
    3532 
    35333546
    35343547/**
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette