PGM.cpp revision d31ded334a29f575e23dc889b603b1a586759348
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * PGM - Page Manager and Monitor. (Mixing stuff here, not good?)
3f1e0eea71cabeb90529e546f16eb7aee513fde9vboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * available from http://www.virtualbox.org. This file is free software;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * additional information or have any questions.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** @page pg_pgm PGM - The Page Manager and Monitor
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @see grp_pgm,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @ref pg_pgm_pool,
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync * @ref pg_pgm_phys.
d31ded334a29f575e23dc889b603b1a586759348vboxsync * @section sec_pgm_modes Paging Modes
d31ded334a29f575e23dc889b603b1a586759348vboxsync * There are three memory contexts: Host Context (HC), Guest Context (GC)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * and intermediate context. When talking about paging HC can also be refered to
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * as "host paging", and GC refered to as "shadow paging".
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * We define three basic paging modes: 32-bit, PAE and AMD64. The host paging mode
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * is defined by the host operating system. The mode used in the shadow paging mode
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * depends on the host paging mode and what the mode the guest is currently in. The
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync * following relation between the two is defined:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @verbatim
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Host > 32-bit | PAE | AMD64 |
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Guest | | | |
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ==v================================
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync 32-bit 32-bit PAE PAE
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync -------|--------|--------|--------|
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PAE PAE PAE PAE
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync -------|--------|--------|--------|
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync AMD64 AMD64 AMD64 AMD64
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync -------|--------|--------|--------| @endverbatim
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * All configuration except those in the diagonal (upper left) are expected to
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * require special effort from the switcher (i.e. a bit slower).
0174432b2b1a760b89840ba696f7ba51def65dddvboxsync * @section sec_pgm_shw The Shadow Memory Context
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync * Because of guest context mappings requires PDPT and PML4 entries to allow
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync * writing on AMD64, the two upper levels will have fixed flags whatever the
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync * guest is thinking of using there. So, when shadowing the PD level we will
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync * calculate the effective flags of PD and all the higher levels. In legacy
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync * PAE mode this only applies to the PWT and PCD bits (the rest are
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync * ignored/reserved/MBZ). We will ignore those bits for the present.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @section sec_pgm_int The Intermediate Memory Context
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The world switch goes thru an intermediate memory context which purpose it is
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * to provide different mappings of the switcher code. All guest mappings are also
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * present in this context.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The switcher code is mapped at the same location as on the host, at an
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * identity mapped location (physical equals virtual address), and at the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * hypervisor location. The identity mapped location is for when the world
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * switches that involves disabling paging.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * PGM maintain page tables for 32-bit, PAE and AMD64 paging modes. This
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * simplifies switching guest CPU mode and consistency at the cost of more
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * code to do the work. All memory use for those page tables is located below
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 4GB (this includes page tables for guest context mappings).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @subsection subsec_pgm_int_gc Guest Context Mappings
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * During assignment and relocation of a guest context mapping the intermediate
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * memory context is used to verify the new location.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Guest context mappings are currently restricted to below 4GB, for reasons
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * of simplicity. This may change when we implement AMD64 support.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @section sec_pgm_misc Misc
a11c569636fa6838bd423f4631a9660a5a84204bvboxsync * @subsection subsec_pgm_misc_diff Differences Between Legacy PAE and Long Mode PAE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The differences between legacy PAE and long mode PAE are:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * -# PDPE bits 1, 2, 5 and 6 are defined differently. In leagcy mode they are
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * all marked down as must-be-zero, while in long mode 1, 2 and 5 have the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * usual meanings while 6 is ignored (AMD). This means that upon switching to
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * legacy PAE mode we'll have to clear these bits and when going to long mode
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * they must be set. This applies to both intermediate and shadow contexts,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * however we don't need to do it for the intermediate one since we're
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * executing with CR0.WP at that time.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * -# CR3 allows a 32-byte aligned address in legacy mode, while in long mode
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * a page aligned one is required.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @section sec_pgm_handlers Access Handlers
3ecf9412133496b2aeb090cfd33a286404ec59fbvboxsync * Placeholder.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @subsection sec_pgm_handlers_virt Virtual Access Handlers
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Placeholder.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @subsection sec_pgm_handlers_virt Virtual Access Handlers
750d4d0506a38b2e80c997075d40aad474e675fbvboxsync * We currently implement three types of virtual access handlers: ALL, WRITE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * and HYPERVISOR (WRITE). See PGMVIRTHANDLERTYPE for some more details.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The HYPERVISOR access handlers is kept in a separate tree since it doesn't apply
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * to physical pages (PGMTREES::HyperVirtHandlers) and only needs to be consulted in
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * a special \#PF case. The ALL and WRITE are in the PGMTREES::VirtHandlers tree, the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * rest of this section is going to be about these handlers.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * We'll go thru the life cycle of a handler and try make sense of it all, don't know
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * how successfull this is gonna be...
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 1. A handler is registered thru the PGMR3HandlerVirtualRegister and
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync * PGMHandlerVirtualRegisterEx APIs. We check for conflicting virtual handlers
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync * and create a new node that is inserted into the AVL tree (range key). Then
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * a full PGM resync is flagged (clear pool, sync cr3, update virtual bit of PGMPAGE).
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * 2. The following PGMSyncCR3/SyncCR3 operation will first make invoke HandlerVirtualUpdate.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * 2a. HandlerVirtualUpdate will will lookup all the pages covered by virtual handlers
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * via the current guest CR3 and update the physical page -> virtual handler
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * translation. Needless to say, this doesn't exactly scale very well. If any changes
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * are detected, it will flag a virtual bit update just like we did on registration.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * PGMPHYS pages with changes will have their virtual handler state reset to NONE.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * 2b. The virtual bit update process will iterate all the pages covered by all the
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * virtual handlers and update the PGMPAGE virtual handler state to the max of all
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * virtual handlers on that page.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * 2c. Back in SyncCR3 we will now flush the entire shadow page cache to make sure
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * we don't miss any alias mappings of the monitored pages.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 2d. SyncCR3 will then proceed with syncing the CR3 table.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 3. \#PF(np,read) on a page in the range. This will cause it to be synced
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * read-only and resumed if it's a WRITE handler. If it's an ALL handler we
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * will call the handlers like in the next step. If the physical mapping has
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * changed we will - some time in the future - perform a handler callback
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * (optional) and update the physical -> virtual handler cache.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 4. \#PF(,write) on a page in the range. This will cause the handler to
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * be invoked.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 5. The guest invalidates the page and changes the physical backing or
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * unmaps it. This should cause the invalidation callback to be invoked
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * (it might not yet be 100% perfect). Exactly what happens next... is
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * this where we mess up and end up out of sync for a while?
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 6. The handler is deregistered by the client via PGMHandlerVirtualDeregister.
1e3cd9c9c95ff352da1331a1789b05fd012c880dvboxsync * We will then set all PGMPAGEs in the physical -> virtual handler cache for
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync * this handler to NONE and trigger a full PGM resync (basically the same
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * as int step 1). Which means 2 is executed again.
3ecd8008b81f02a04220705ae0033142af363280vboxsync * @subsubsection sub_sec_pgm_handler_virt_todo TODOs
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * There is a bunch of things that needs to be done to make the virtual handlers
576d4214137bce409cdcf01e8df4a0bca5e0b2d1vboxsync * work 100% correctly and work more efficiently.
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * The first bit hasn't been implemented yet because it's going to slow the
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * whole mess down even more, and besides it seems to be working reliably for
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * our current uses. OTOH, some of the optimizations might end up more or less
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * implementing the missing bits, so we'll see.
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * On the optimization side, the first thing to do is to try avoid unnecessary
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * cache flushing. Then try team up with the shadowing code to track changes
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * in mappings by means of access to them (shadow in), updates to shadows pages,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * invlpg, and shadow PT discarding (perhaps).
3ecd8008b81f02a04220705ae0033142af363280vboxsync * Some idea that have popped up for optimization for current and new features:
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * - bitmap indicating where there are virtual handlers installed.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * (4KB => 2**20 pages, page 2**12 => covers 32-bit address space 1:1!)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * - Further optimize this by min/max (needs min/max avl getters).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * - Shadow page table entry bit (if any left)?
247b55faa8d054157f2481e68caca36f4dc9542cvboxsync/** @page pg_pgm_phys PGM Physical Guest Memory Management
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * Objectives:
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync * - Guest RAM over-commitment using memory ballooning,
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * zero pages and general page sharing.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * - Moving or mirroring a VM onto a different physical machine.
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync * @subsection subsec_pgmPhys_Definitions Definitions
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync * Allocation chunk - A RTR0MemObjAllocPhysNC object and the tracking
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync * machinery assoicated with it.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @subsection subsec_pgmPhys_AllocPage Allocating a page.
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * Initially we map *all* guest memory to the (per VM) zero page, which
b978e5849454446957177fd47ee98609ab0457a6vboxsync * means that none of the read functions will cause pages to be allocated.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Exception, access bit in page tables that have been shared. This must
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * be handled, but we must also make sure PGMGst*Modify doesn't make
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * unnecessary modifications.
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * Allocation points:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * - PGMPhysSimpleWriteGCPhys and PGMPhysWrite.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * - Replacing a zero page mapping at \#PF.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * - Replacing a shared page mapping at \#PF.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * - ROM registration (currently MMR3RomRegister).
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * - VM restore (pgmR3Load).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * For the first three it would make sense to keep a few pages handy
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * until we've reached the max memory commitment for the VM.
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync * For the ROM registration, we know exactly how many pages we need
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * and will request these from ring-0. For restore, we will save
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the number of non-zero pages in the saved state and allocate
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * them up front. This would allow the ring-0 component to refuse
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the request if the isn't sufficient memory available for VM use.
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * Btw. for both ROM and restore allocations we won't be requiring
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * zeroed pages as they are going to be filled instantly.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * @subsection subsec_pgmPhys_FreePage Freeing a page
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * There are a few points where a page can be freed:
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * - After being replaced by the zero page.
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * - After being replaced by a shared page.
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync * - After being ballooned by the guest additions.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * - At reset.
e50404712a2b5234c42bdf9740bddab5729ba188vboxsync * - At restore.
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync * When freeing one or more pages they will be returned to the ring-0
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * component and replaced by the zero page.
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * The reasoning for clearing out all the pages on reset is that it will
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * return us to the exact same state as on power on, and may thereby help
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * us reduce the memory load on the system. Further it might have a
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * (temporary) positive influence on memory fragmentation (@see subsec_pgmPhys_Fragmentation).
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * On restore, as mention under the allocation topic, pages should be
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * freed / allocated depending on how many is actually required by the
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * new VM state. The simplest approach is to do like on reset, and free
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * all non-ROM pages and then allocate what we need.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * A measure to prevent some fragmentation, would be to let each allocation
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * chunk have some affinity towards the VM having allocated the most pages
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * from it. Also, try make sure to allocate from allocation chunks that
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * are almost full. Admittedly, both these measures might work counter to
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * our intentions and its probably not worth putting a lot of effort,
34e34d3656484dde89a9c7b57fcbf7048d2fdb13vboxsync * cpu time or memory into this.
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync * @subsection subsec_pgmPhys_SharePage Sharing a page
ebbb1f6c7e8bae363a4efda4b35b58c8467d24bcvboxsync * The basic idea is that there there will be a idle priority kernel
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * thread walking the non-shared VM pages hashing them and looking for
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * pages with the same checksum. If such pages are found, it will compare
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * them byte-by-byte to see if they actually are identical. If found to be
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * identical it will allocate a shared page, copy the content, check that
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * the page didn't change while doing this, and finally request both the
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * VMs to use the shared page instead. If the page is all zeros (special
ebbb1f6c7e8bae363a4efda4b35b58c8467d24bcvboxsync * checksum and byte-by-byte check) it will request the VM that owns it
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * to replace it with the zero page.
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * To make this efficient, we will have to make sure not to try share a page
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * that will change its contents soon. This part requires the most work.
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * A simple idea would be to request the VM to write monitor the page for
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * a while to make sure it isn't modified any time soon. Also, it may
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * make sense to skip pages that are being write monitored since this
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * information is readily available to the thread if it works on the
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * per-VM guest memory structures (presently called PGMRAMRANGE).
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * @subsection subsec_pgmPhys_Fragmentation Fragmentation Concerns and Counter Measures
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * The pages are organized in allocation chunks in ring-0, this is a necessity
34e34d3656484dde89a9c7b57fcbf7048d2fdb13vboxsync * if we wish to have an OS agnostic approach to this whole thing. (On Linux we
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * could easily work on a page-by-page basis if we liked. Whether this is possible
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * or efficient on NT I don't quite know.) Fragmentation within these chunks may
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync * become a problem as part of the idea here is that we wish to return memory to
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * the host system.
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * For instance, starting two VMs at the same time, they will both allocate the
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * guest memory on-demand and if permitted their page allocations will be
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * intermixed. Shut down one of the two VMs and it will be difficult to return
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * any memory to the host system because the page allocation for the two VMs are
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * mixed up in the same allocation chunks.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * To further complicate matters, when pages are freed because they have been
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * ballooned or become shared/zero the whole idea is that the page is supposed
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync * to be reused by another VM or returned to the host system. This will cause
e52f819639386db020b2a635b47a415248c7fbf9vboxsync * allocation chunks to contain pages belonging to different VMs and prevent
b978e5849454446957177fd47ee98609ab0457a6vboxsync * returning memory to the host when one of those VM shuts down.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The only way to really deal with this problem is to move pages. This can
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * either be done at VM shutdown and or by the idle priority worker thread
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * that will be responsible for finding sharable/zero pages. The mechanisms
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * involved for coercing a VM to move a page (or to do it for it) will be
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * the same as when telling it to share/zero a page.
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * @subsection subsec_pgmPhys_Tracking Tracking Structures And Their Cost
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync * There's a difficult balance between keeping the per-page tracking structures
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * (global and guest page) easy to use and keeping them from eating too much
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * memory. We have limited virtual memory resources available when operating in
0e77737b0ba913683e614db11463b31ca67aacbevboxsync * 32-bit kernel space (on 64-bit there'll it's quite a different story). The
0e77737b0ba913683e614db11463b31ca67aacbevboxsync * tracking structures will be attemted designed such that we can deal with up
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * to 32GB of memory on a 32-bit system and essentially unlimited on 64-bit ones.
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync * @subsubsection subsubsec_pgmPhys_Tracking_Kernel Kernel Space
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync * @see pg_GMM
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync * @subsubsection subsubsec_pgmPhys_Tracking_PerVM Per-VM
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * Fixed info is the physical address of the page (HCPhys) and the page id
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * (described above). Theoretically we'll need 48(-12) bits for the HCPhys part.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * Today we've restricting ourselves to 40(-12) bits because this is the current
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * restrictions of all AMD64 implementations (I think Barcelona will up this
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * to 48(-12) bits, not that it really matters) and I needed the bits for
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * tracking mappings of a page. 48-12 = 36. That leaves 28 bits, which means a
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync * decent range for the page id: 2^(28+12) = 1024TB.
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * In additions to these, we'll have to keep maintaining the page flags as we
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync * currently do. Although it wouldn't harm to optimize these quite a bit, like
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync * for instance the ROM shouldn't depend on having a write handler installed
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * in order for it to become read-only. A RO/RW bit should be considered so
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync * that the page syncing code doesn't have to mess about checking multiple
0e77737b0ba913683e614db11463b31ca67aacbevboxsync * flag combinations (ROM || RW handler || write monitored) in order to
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * figure out how to setup a shadow PTE. But this of course, is second
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * priority at present. Current this requires 12 bits, but could probably
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * be optimized to ~8.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Then there's the 24 bits used to track which shadow page tables are
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync * currently mapping a page for the purpose of speeding up physical
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * access handlers, and thereby the page pool cache. More bit for this
8e972b677df5ee27b99211fc7e456a5aa50f3e68vboxsync * purpose wouldn't hurt IIRC.
b978e5849454446957177fd47ee98609ab0457a6vboxsync * Then there is a new bit in which we need to record what kind of page
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * this is, shared, zero, normal or write-monitored-normal. This'll
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * require 2 bits. One bit might be needed for indicating whether a
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * write monitored page has been written to. And yet another one or
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * two for tracking migration status. 3-4 bits total then.
1986f56777969a25707ab214f8dd070804be666cvboxsync * Whatever is left will can be used to record the sharabilitiy of a
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * page. The page checksum will not be stored in the per-VM table as
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * the idle thread will not be permitted to do modifications to it.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * It will instead have to keep its own working set of potentially
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * shareable pages and their check sums and stuff.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * For the present we'll keep the current packing of the
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * PGMRAMRANGE::aHCPhys to keep the changes simple, only of course,
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * we'll have to change it to a struct with a total of 128-bits at
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * our disposal.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * The initial layout will be like this:
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * @verbatim
34e34d3656484dde89a9c7b57fcbf7048d2fdb13vboxsync RTHCPHYS HCPhys; The current stuff.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync 63:40 Current shadow PT tracking stuff.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync 39:12 The physical page frame number.
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync 11:0 The current flags.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync uint32_t u28PageId : 28; The page id.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync uint32_t u2State : 2; The page state { zero, shared, normal, write monitored }.
d98e61ba075ed7d0b567a5d884bc85d643fe3de7vboxsync uint32_t fWrittenTo : 1; Whether a write monitored page was written to.
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync uint32_t u1Reserved : 1; Reserved for later.
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync uint32_t u32Reserved; Reserved for later, mostly sharing stats.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync @endverbatim
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The final layout will be something like this:
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * @verbatim
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTHCPHYS HCPhys; The current stuff.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync 63:48 High page id (12+).
806d0b554daa555364af5f87bc96eccbe760db7avboxsync 47:12 The physical page frame number.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync 11:0 Low page id.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync uint32_t fReadOnly : 1; Whether it's readonly page (rom or monitored in some way).
1986f56777969a25707ab214f8dd070804be666cvboxsync uint32_t u3Type : 3; The page type {RESERVED, MMIO, MMIO2, ROM, shadowed ROM, RAM}.
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync uint32_t u2PhysMon : 2; Physical access handler type {none, read, write, all}.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync uint32_t u2VirtMon : 2; Virtual access handler type {none, read, write, all}..
e149c362e69e5f0bbd82da11fd8163b2d29c3a72vboxsync uint32_t u2State : 2; The page state { zero, shared, normal, write monitored }.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync uint32_t fWrittenTo : 1; Whether a write monitored page was written to.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync uint32_t u20Reserved : 20; Reserved for later, mostly sharing stats.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync uint32_t u32Tracking; The shadow PT tracking stuff, roughly.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync @endverbatim
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * Cost wise, this means we'll double the cost for guest memory. There isn't anyway
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * around that I'm afraid. It means that the cost of dealing out 32GB of memory
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * to one or more VMs is: (32GB >> PAGE_SHIFT) * 16 bytes, or 128MBs. Or another
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * example, the VM heap cost when assigning 1GB to a VM will be: 4MB.
34e34d3656484dde89a9c7b57fcbf7048d2fdb13vboxsync * A couple of cost examples for the total cost per-VM + kernel.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * 32-bit Windows and 32-bit linux:
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * 1GB guest ram, 256K pages: 4MB + 2MB(+) = 6MB
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync * 4GB guest ram, 1M pages: 16MB + 8MB(+) = 24MB
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * 32GB guest ram, 8M pages: 128MB + 64MB(+) = 192MB
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * 64-bit Windows and 64-bit linux:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 1GB guest ram, 256K pages: 4MB + 3MB(+) = 7MB
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 4GB guest ram, 1M pages: 16MB + 12MB(+) = 28MB
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 32GB guest ram, 8M pages: 128MB + 96MB(+) = 224MB
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * UPDATE - 2007-09-27:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Will need a ballooned flag/state too because we cannot
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * trust the guest 100% and reporting the same page as ballooned more
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync * than once will put the GMM off balance.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * @subsection subsec_pgmPhys_Serializing Serializing Access
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Initially, we'll try a simple scheme:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * - The per-VM RAM tracking structures (PGMRAMRANGE) is only modified
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * by the EMT thread of that VM while in the pgm critsect.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * - Other threads in the VM process that needs to make reliable use of
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * the per-VM RAM tracking structures will enter the critsect.
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * - No process external thread or kernel thread will ever try enter
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync * the pgm critical section, as that just won't work.
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync * - The idle thread (and similar threads) doesn't not need 100% reliable
b978e5849454446957177fd47ee98609ab0457a6vboxsync * data when performing it tasks as the EMT thread will be the one to
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * do the actual changes later anyway. So, as long as it only accesses
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * the main ram range, it can do so by somehow preventing the VM from
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * being destroyed while it works on it...
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * - The over-commitment management, including the allocating/freeing
1986f56777969a25707ab214f8dd070804be666cvboxsync * chunks, is serialized by a ring-0 mutex lock (a fast one since the
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * more mundane mutex implementation is broken on Linux).
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * - A separeate mutex is protecting the set of allocation chunks so
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * that pages can be shared or/and freed up while some other VM is
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * allocating more chunks. This mutex can be take from under the other
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync * one, but not the otherway around.
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync * @subsection subsec_pgmPhys_Request VM Request interface
1157941288c9533575a655c660af55d13da31eefvboxsync * When in ring-0 it will become necessary to send requests to a VM so it can
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync * for instance move a page while defragmenting during VM destroy. The idle
1157941288c9533575a655c660af55d13da31eefvboxsync * thread will make use of this interface to request VMs to setup shared
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync * pages and to perform write monitoring of pages.
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync * I would propose an interface similar to the current VMReq interface, similar
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync * in that it doesn't require locking and that the one sending the request may
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * wait for completion if it wishes to. This shouldn't be very difficult to
7bae75e0b207aa4d4cad2a951271ad1a0e8ab9fdvboxsync * The requests themselves are also pretty simple. They are basically:
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync * -# Check that some precondition is still true.
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync * -# Do the update.
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync * -# Update all shadow page tables involved with the page.
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * The 3rd step is identical to what we're already doing when updating a
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * physical handler, see pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs.
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync * @section sec_pgmPhys_MappingCaches Mapping Caches
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * In order to be able to map in and out memory and to be able to support
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * guest with more RAM than we've got virtual address space, we'll employing
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * a mapping cache. There is already a tiny one for GC (see PGMGCDynMapGCPageEx)
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * and we'll create a similar one for ring-0 unless we decide to setup a dedicate
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * memory context for the HWACCM execution.
e149c362e69e5f0bbd82da11fd8163b2d29c3a72vboxsync * @subsection subsec_pgmPhys_MappingCaches_R3 Ring-3
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * We've considered implementing the ring-3 mapping cache page based but found
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * that this was bother some when one had to take into account TLBs+SMP and
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync * portability (missing the necessary APIs on several platforms). There were
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * also some performance concerns with this approach which hadn't quite been
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * worked out.
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync * Instead, we'll be mapping allocation chunks into the VM process. This simplifies
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * matters greatly quite a bit since we don't need to invent any new ring-0 stuff,
34e34d3656484dde89a9c7b57fcbf7048d2fdb13vboxsync * only some minor RTR0MEMOBJ mapping stuff. The main concern here is that mapping
7bae75e0b207aa4d4cad2a951271ad1a0e8ab9fdvboxsync * compared to the previous idea is that mapping or unmapping a 1MB chunk is more
7bae75e0b207aa4d4cad2a951271ad1a0e8ab9fdvboxsync * costly than a single page, although how much more costly is uncertain. We'll
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync * try address this by using a very big cache, preferably bigger than the actual
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync * VM RAM size if possible. The current VM RAM sizes should give some idea for
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * 32-bit boxes, while on 64-bit we can probably get away with employing an
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * unlimited cache.
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * The cache have to parts, as already indicated, the ring-3 side and the
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync * ring-0 side.
b978e5849454446957177fd47ee98609ab0457a6vboxsync * The ring-0 will be tied to the page allocator since it will operate on the
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync * memory objects it contains. It will therefore require the first ring-0 mutex
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync * discussed in @ref subsec_pgmPhys_Serializing. We
7082d29724f6c3788977a51591b0379fd3acbf72vboxsync * some double house keeping wrt to who has mapped what I think, since both
7082d29724f6c3788977a51591b0379fd3acbf72vboxsync * VMMR0.r0 and RTR0MemObj will keep track of mapping relataions
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * The ring-3 part will be protected by the pgm critsect. For simplicity, we'll
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * require anyone that desires to do changes to the mapping cache to do that
46b1ac1c3302722f93e787d0f0693965e88f5ceevboxsync * from within this critsect. Alternatively, we could employ a separate critsect
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync * for serializing changes to the mapping cache as this would reduce potential
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * contention with other threads accessing mappings unrelated to the changes
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync * that are in process. We can see about this later, contention will show
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * up in the statistics anyway, so it'll be simple to tell.
f827fea1108b8f8a1a5f63318f6ec3cf4a9e7010vboxsync * The organization of the ring-3 part will be very much like how the allocation
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * chunks are organized in ring-0, that is in an AVL tree by chunk id. To avoid
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * having to walk the tree all the time, we'll have a couple of lookaside entries
1986f56777969a25707ab214f8dd070804be666cvboxsync * like in we do for I/O ports and MMIO in IOM.
5cf54b3ffeb7ee90685dcaec329ef71a729f5947vboxsync * The simplified flow of a PGMPhysRead/Write function:
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * -# Enter the PGM critsect.
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * -# Lookup GCPhys in the ram ranges and get the Page ID.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * -# Calc the Allocation Chunk ID from the Page ID.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * -# Check the lookaside entries and then the AVL tree for the Chunk ID.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * If not found in cache:
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * -# Call ring-0 and request it to be mapped and supply
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * a chunk to be unmapped if the cache is maxed out already.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * -# Insert the new mapping into the AVL tree (id + R3 address).
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * -# Update the relevant lookaside entry and return the mapping address.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * -# Do the read/write according to monitoring flags and everything.
9f9a20823b87e89c1b5cb45eb9b5699b29bfefebvboxsync * -# Leave the critsect.
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync * @section sec_pgmPhys_Fallback Fallback
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * Current all the "second tier" hosts will not support the RTR0MemObjAllocPhysNC
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * API and thus require a fallback.
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * So, when RTR0MemObjAllocPhysNC returns VERR_NOT_SUPPORTED the page allocator
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * will return to the ring-3 caller (and later ring-0) and asking it to seed
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * the page allocator with some fresh pages (VERR_GMM_SEED_ME). Ring-3 will
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * then perform an SUPR3PageAlloc(cbChunk >> PAGE_SHIFT) call and make a
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * "SeededAllocPages" call to ring-0.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * The first time ring-0 sees the VERR_NOT_SUPPORTED failure it will disable
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * all page sharing (zero page detection will continue). It will also force
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * all allocations to come from the VM which seeded the page. Both these
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * measures are taken to make sure that there will never be any need for
1986f56777969a25707ab214f8dd070804be666cvboxsync * mapping anything into ring-3 - everything will be mapped already.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * Whether we'll continue to use the current MM locked memory management
e149c362e69e5f0bbd82da11fd8163b2d29c3a72vboxsync * for this I don't quite know (I'd prefer not to and just ditch that all
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * togther), we'll see what's simplest to do.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * @section sec_pgmPhys_Changes Changes
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * Breakdown of the changes involved?
9f9a20823b87e89c1b5cb45eb9b5699b29bfefebvboxsync/*******************************************************************************
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync* Header Files *
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync*******************************************************************************/
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync/*******************************************************************************
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync* Defined Constants And Macros *
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync*******************************************************************************/
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync/** Saved state data unit version for 2.5.x and later. */
22e281e75ed636601178296c6daebda8f1d17c59vboxsync/** Saved state data unit version for 2.2.2 and later. */
8e8844a522f5d335f177a0313b03067d79cce201vboxsync/** Saved state data unit version for 2.2.0. */
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync/** Saved state data unit version. */
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync/*******************************************************************************
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync* Internal Functions *
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync*******************************************************************************/
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsyncstatic DECLCALLBACK(void) pgmR3PhysInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsyncstatic DECLCALLBACK(void) pgmR3InfoMode(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsyncstatic DECLCALLBACK(void) pgmR3InfoCr3(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsyncstatic DECLCALLBACK(int) pgmR3RelocatePhysHandler(PAVLROGCPHYSNODECORE pNode, void *pvUser);
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsyncstatic DECLCALLBACK(int) pgmR3RelocateVirtHandler(PAVLROGCPTRNODECORE pNode, void *pvUser);
ce2d2eef2525963979102e63c2419d1c69d767ccvboxsyncstatic DECLCALLBACK(int) pgmR3RelocateHyperVirtHandler(PAVLROGCPTRNODECORE pNode, void *pvUser);
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsyncstatic DECLCALLBACK(void) pgmR3ResetNoMorePhysWritesFlag(PVM pVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser);
9f9a20823b87e89c1b5cb45eb9b5699b29bfefebvboxsyncstatic int pgmR3ModeDataInit(PVM pVM, bool fResolveGCAndR0);
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsyncstatic void pgmR3ModeDataSwitch(PVM pVM, PVMCPU pVCpu, PGMMODE enmShw, PGMMODE enmGst);
ce2d2eef2525963979102e63c2419d1c69d767ccvboxsyncstatic PGMMODE pgmR3CalcShadowMode(PVM pVM, PGMMODE enmGuestMode, SUPPAGINGMODE enmHostMode, PGMMODE enmShadowMode, VMMSWITCHER *penmSwitcher);
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync/** @todo Convert the first two commands to 'info' items. */
ce2d2eef2525963979102e63c2419d1c69d767ccvboxsyncstatic DECLCALLBACK(int) pgmR3CmdRam(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
ce2d2eef2525963979102e63c2419d1c69d767ccvboxsyncstatic DECLCALLBACK(int) pgmR3CmdError(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
ce2d2eef2525963979102e63c2419d1c69d767ccvboxsyncstatic DECLCALLBACK(int) pgmR3CmdSync(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsyncstatic DECLCALLBACK(int) pgmR3CmdSyncAlways(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
9f9a20823b87e89c1b5cb45eb9b5699b29bfefebvboxsyncstatic DECLCALLBACK(int) pgmR3CmdAssertCR3(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsyncstatic DECLCALLBACK(int) pgmR3CmdPhysToFile(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync/*******************************************************************************
5db1d52ffbcaa46c3d944c6c2d9c552306817d9avboxsync* Global Variables *
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync*******************************************************************************/
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync/** Argument descriptors for '.pgmerror' and '.pgmerroroff'. */
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync { 0, 1, DBGCVAR_CAT_STRING, 0, "where", "Error injection location." },
9673b0b804d0b0f801f377c6371600e92071241fvboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync { 1, 1, DBGCVAR_CAT_STRING, 0, "file", "The file name." },
ce2d2eef2525963979102e63c2419d1c69d767ccvboxsync { 0, 1, DBGCVAR_CAT_STRING, 0, "nozero", "If present, zero pages are skipped." },
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync/** Command descriptors. */
ce2d2eef2525963979102e63c2419d1c69d767ccvboxsync /* pszCmd, cArgsMin, cArgsMax, paArgDesc, cArgDescs, pResultDesc, fFlags, pfnHandler pszSyntax, ....pszDescription */
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync { "pgmram", 0, 0, NULL, 0, NULL, 0, pgmR3CmdRam, "", "Display the ram ranges." },
ce2d2eef2525963979102e63c2419d1c69d767ccvboxsync { "pgmsync", 0, 0, NULL, 0, NULL, 0, pgmR3CmdSync, "", "Sync the CR3 page." },
9673b0b804d0b0f801f377c6371600e92071241fvboxsync { "pgmerror", 0, 1, &g_aPgmErrorArgs[0], 1, NULL, 0, pgmR3CmdError, "", "Enables inject runtime of errors into parts of PGM." },
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync { "pgmerroroff", 0, 1, &g_aPgmErrorArgs[0], 1, NULL, 0, pgmR3CmdError, "", "Disables inject runtime errors into parts of PGM." },
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync { "pgmassertcr3", 0, 0, NULL, 0, NULL, 0, pgmR3CmdAssertCR3, "", "Check the shadow CR3 mapping." },
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync { "pgmsyncalways", 0, 0, NULL, 0, NULL, 0, pgmR3CmdSyncAlways, "", "Toggle permanent CR3 syncing." },
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync { "pgmphystofile", 1, 2, &g_aPgmPhysToFileArgs[0], 2, NULL, 0, pgmR3CmdPhysToFile, "", "Save the physical memory to file." },
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Shadow - 32-bit mode
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_SHW_NAME_RC_STR(name) PGM_SHW_NAME_RC_32BIT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_SHW_NAME_R0_STR(name) PGM_SHW_NAME_R0_32BIT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - real mode */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_REAL_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_REAL_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_REAL(name)
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_32BIT_REAL_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_32BIT_REAL_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_32BIT_PT_FOR_PHYS
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_32BIT_PD_PHYS
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - protected mode */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_PROT_STR(name)
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_PROT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_PROT(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_32BIT_PROT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_32BIT_PROT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_32BIT_PT_FOR_PHYS
5b6e2c9a765c3c72295acc15791af8a700746956vboxsync#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_32BIT_PD_PHYS
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync/* Guest - 32-bit mode */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_32BIT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_32BIT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_32BIT_32BIT(name)
5ace91141404400247438502a84a418fba00c8cfvboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_32BIT_32BIT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_32BIT_32BIT_STR(name)
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_32BIT_PT_FOR_32BIT_PT
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_32BIT_PT_FOR_32BIT_4MB
49748bb305bd71f672cd083af208f4bb08c5d6abvboxsync * Shadow - PAE mode
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_SHW_NAME_RC_STR(name) PGM_SHW_NAME_RC_PAE_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_SHW_NAME_R0_STR(name) PGM_SHW_NAME_R0_PAE_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_REAL(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - real mode */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_REAL_STR(name)
b9ca93dd1ad44cb8b27679dc5624be2f7b7f7af5vboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_REAL_STR(name)
b9ca93dd1ad44cb8b27679dc5624be2f7b7f7af5vboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_REAL(name)
b9ca93dd1ad44cb8b27679dc5624be2f7b7f7af5vboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_PAE_REAL_STR(name)
b9ca93dd1ad44cb8b27679dc5624be2f7b7f7af5vboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_PAE_REAL_STR(name)
b9ca93dd1ad44cb8b27679dc5624be2f7b7f7af5vboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
b9ca93dd1ad44cb8b27679dc5624be2f7b7f7af5vboxsync#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_PAE_PDPT_PHYS
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - protected mode */
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_PROT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_PROT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_PROT(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_PAE_PROT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_PAE_PROT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_PAE_PDPT_PHYS
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync/* Guest - 32-bit mode */
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_32BIT_STR(name)
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_32BIT_STR(name)
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_32BIT(name)
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_PAE_32BIT_STR(name)
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_PAE_32BIT_STR(name)
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_32BIT_PT
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_32BIT_4MB
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_PAE_PDPT_FOR_32BIT
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync/* Guest - PAE mode */
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_PAE_STR(name)
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_PAE_STR(name)
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_PAE(name)
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_PAE_PAE_STR(name)
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_PAE_PAE_STR(name)
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PAE_PT
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Shadow - AMD64 mode
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_SHW_NAME_RC_STR(name) PGM_SHW_NAME_RC_AMD64_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_SHW_NAME_R0_STR(name) PGM_SHW_NAME_R0_AMD64_STR(name)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync/* Guest - AMD64 mode */
5ace91141404400247438502a84a418fba00c8cfvboxsync# define PGM_GST_NAME(name) PGM_GST_NAME_AMD64(name)
5ace91141404400247438502a84a418fba00c8cfvboxsync# define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_AMD64_STR(name)
5ace91141404400247438502a84a418fba00c8cfvboxsync# define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_AMD64_STR(name)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync# define PGM_BTH_NAME(name) PGM_BTH_NAME_AMD64_AMD64(name)
5ace91141404400247438502a84a418fba00c8cfvboxsync# define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_AMD64_AMD64_STR(name)
5ace91141404400247438502a84a418fba00c8cfvboxsync# define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_AMD64_AMD64_STR(name)
3123bb2477edc752585e4bbd8e4cfedaf87997d1vboxsync# define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PAE_PT
247b55faa8d054157f2481e68caca36f4dc9542cvboxsync# define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
247b55faa8d054157f2481e68caca36f4dc9542cvboxsync# define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_64BIT_PML4
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync#endif /* VBOX_WITH_64_BITS_GUESTS */
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * Shadow - Nested paging mode
d07ea3c3faead54c0de83ab93f2b03dedfb819e2vboxsync#define PGM_SHW_NAME(name) PGM_SHW_NAME_NESTED(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_SHW_NAME_RC_STR(name) PGM_SHW_NAME_RC_NESTED_STR(name)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync#define PGM_SHW_NAME_R0_STR(name) PGM_SHW_NAME_R0_NESTED_STR(name)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync/* Guest - real mode */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_REAL_STR(name)
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_REAL_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_NESTED_REAL(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_NESTED_REAL_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_NESTED_REAL_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - protected mode */
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_PROT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_PROT_STR(name)
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_NESTED_PROT(name)
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_NESTED_PROT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_NESTED_PROT_STR(name)
247b55faa8d054157f2481e68caca36f4dc9542cvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync/* Guest - 32-bit mode */
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_32BIT_STR(name)
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_32BIT_STR(name)
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_NESTED_32BIT(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_NESTED_32BIT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_NESTED_32BIT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_32BIT_PT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_32BIT_4MB
5b6e2c9a765c3c72295acc15791af8a700746956vboxsync/* Guest - PAE mode */
036d626c5d4722da925dc8292f9248a5e09b4588vboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_PAE_STR(name)
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_PAE_STR(name)
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_NESTED_PAE(name)
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_NESTED_PAE_STR(name)
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_NESTED_PAE_STR(name)
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PAE_PT
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync/* Guest - AMD64 mode */
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync# define PGM_GST_NAME(name) PGM_GST_NAME_AMD64(name)
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync# define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_AMD64_STR(name)
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync# define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_AMD64_STR(name)
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync# define PGM_BTH_NAME(name) PGM_BTH_NAME_NESTED_AMD64(name)
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync# define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_NESTED_AMD64_STR(name)
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync# define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_NESTED_AMD64_STR(name)
036d626c5d4722da925dc8292f9248a5e09b4588vboxsync# define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PAE_PT
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync# define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_64_BITS_GUESTS */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Shadow - EPT
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync#define PGM_SHW_NAME_RC_STR(name) PGM_SHW_NAME_RC_EPT_STR(name)
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync#define PGM_SHW_NAME_R0_STR(name) PGM_SHW_NAME_R0_EPT_STR(name)
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync/* Guest - real mode */
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_REAL_STR(name)
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_REAL_STR(name)
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_REAL(name)
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_EPT_REAL_STR(name)
6778b34cb96bef0fef23ebc461eb6a429d2907c5vboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_EPT_REAL_STR(name)
614cbe11a7e5588dc8d369e223174b1441a09359vboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync/* Guest - protected mode */
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_PROT_STR(name)
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_PROT_STR(name)
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_PROT(name)
614cbe11a7e5588dc8d369e223174b1441a09359vboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_EPT_PROT_STR(name)
614cbe11a7e5588dc8d369e223174b1441a09359vboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_EPT_PROT_STR(name)
b5b12033c1f7eaf82b038f06e2b9e464b9ddd8d2vboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
d4b98dbce4cf7b3694b62d62a47553d399718dccvboxsync/* Guest - 32-bit mode */
fd69ca9bd8b533bfa9ade45c1c2ff3116854e84avboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_32BIT_STR(name)
fd69ca9bd8b533bfa9ade45c1c2ff3116854e84avboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_32BIT_STR(name)
fd69ca9bd8b533bfa9ade45c1c2ff3116854e84avboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_32BIT(name)
fd69ca9bd8b533bfa9ade45c1c2ff3116854e84avboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_EPT_32BIT_STR(name)
fd69ca9bd8b533bfa9ade45c1c2ff3116854e84avboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_EPT_32BIT_STR(name)
fd69ca9bd8b533bfa9ade45c1c2ff3116854e84avboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_32BIT_PT
b978e5849454446957177fd47ee98609ab0457a6vboxsync#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_32BIT_4MB
5ace91141404400247438502a84a418fba00c8cfvboxsync/* Guest - PAE mode */
5ace91141404400247438502a84a418fba00c8cfvboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_PAE_STR(name)
5ace91141404400247438502a84a418fba00c8cfvboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_PAE_STR(name)
5ace91141404400247438502a84a418fba00c8cfvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_PAE(name)
5ace91141404400247438502a84a418fba00c8cfvboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_EPT_PAE_STR(name)
5a12b9772d9cf396a0ba7f54db399817ba7a65bavboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_EPT_PAE_STR(name)
01c7ae36dfb7eb93bef22d5ec6c1c0572eba3f24vboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PAE_PT
5a12b9772d9cf396a0ba7f54db399817ba7a65bavboxsync#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - AMD64 mode */
0f5d1b2abd9e82c7ee46f1327287c44856604bcbvboxsync# define PGM_GST_NAME(name) PGM_GST_NAME_AMD64(name)
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync# define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_AMD64_STR(name)
5ace91141404400247438502a84a418fba00c8cfvboxsync# define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_AMD64_STR(name)
f8b934f4817639cddebe4d3c2ae25d39a91fe448vboxsync# define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_AMD64(name)
20a793635760c71752932fde640ba328cab84348vboxsync# define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_EPT_AMD64_STR(name)
5ace91141404400247438502a84a418fba00c8cfvboxsync# define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_EPT_AMD64_STR(name)
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync# define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PAE_PT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync#endif /* VBOX_WITH_64_BITS_GUESTS */
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync * Initiates the paging of VM.
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync * @returns VBox status code.
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync * @param pVM Pointer to VM structure.
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync PCFGMNODE pCfgPGM = CFGMR3GetChild(CFGMR3GetRoot(pVM), "/PGM");
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync * Assert alignment and sizes.
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync AssertCompile(sizeof(pVM->pgm.s) <= sizeof(pVM->pgm.padding));
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync AssertCompile(sizeof(pVM->aCpus[0].pgm.s) <= sizeof(pVM->aCpus[0].pgm.padding));
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync AssertCompileMemberAlignment(PGM, CritSect, sizeof(uintptr_t));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Init the structure.
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync /* Init the per-CPU part. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync pPGM->offVM = (uintptr_t)&pVCpu->pgm.s - (uintptr_t)pVM;
28c928d1100d3b6a6d3506224cae25ad04732f73vboxsync pPGM->offPGM = (uintptr_t)&pVCpu->pgm.s - (uintptr_t)&pVM->pgm.s;
28c928d1100d3b6a6d3506224cae25ad04732f73vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pVCpu->pgm.s.apGstPaePDsR3); i++)
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync pVM->pgm.s.GCPhys4MBPSEMask = RT_BIT_64(32) - 1; /* default; checked later */
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync pVM->pgm.s.GCPtrPrevRamRangeMapping = MM_HYPER_AREA_ADDRESS;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = CFGMR3QueryBoolDef(CFGMR3GetRoot(pVM), "RamPreAlloc", &pVM->pgm.s.fRamPreAlloc,
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync#if HC_ARCH_BITS == 64 || 1 /** @todo 4GB/32-bit: remove || 1 later and adjust the limit. */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync rc = CFGMR3QueryU32Def(pCfgPGM, "MaxRing3Chunks", &pVM->pgm.s.ChunkR3Map.cMax, UINT32_MAX);
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync rc = CFGMR3QueryU32Def(pCfgPGM, "MaxRing3Chunks", &pVM->pgm.s.ChunkR3Map.cMax, _1G / GMM_CHUNK_SIZE);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync for (uint32_t i = 0; i < RT_ELEMENTS(pVM->pgm.s.ChunkR3Map.Tlb.aEntries); i++)
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.ChunkR3Map.Tlb.aEntries[i].idChunk = NIL_GMM_CHUNKID;
e17f587595bd5d3a7be56a892e3fd3a0ef83d268vboxsync * Get the configured RAM size - to estimate saved state size.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync rc = CFGMR3QueryU64(CFGMR3GetRoot(pVM), "RamSize", &cbRam);
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync AssertMsgFailed(("Configuration error: Failed to query integer \"RamSize\", rc=%Rrc.\n", rc));
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync * Register callbacks, string formatters and the saved state data unit.
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync VMR3AtStateRegister(pVM, pgmR3ResetNoMorePhysWritesFlag, NULL);
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync * Initialize the PGM critical section and flush the phys TLBs
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync rc = PDMR3CritSectInit(pVM, &pVM->pgm.s.CritSect, RT_SRC_POS, "PGM");
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * For the time being we sport a full set of handy pages in addition to the base
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * memory to simplify things.
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync rc = MMR3ReserveHandyPages(pVM, RT_ELEMENTS(pVM->pgm.s.aHandyPages)); /** @todo this should be changed to PGM_HANDY_PAGES_MIN but this needs proper testing... */
e17f587595bd5d3a7be56a892e3fd3a0ef83d268vboxsync rc = MMHyperAlloc(pVM, sizeof(PGMTREES), 0, MM_TAG_PGM, (void **)&pVM->pgm.s.pTreesR3);
e17f587595bd5d3a7be56a892e3fd3a0ef83d268vboxsync pVM->pgm.s.pTreesR0 = MMHyperR3ToR0(pVM, pVM->pgm.s.pTreesR3);
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync pVM->pgm.s.pTreesRC = MMHyperR3ToRC(pVM, pVM->pgm.s.pTreesR3);
e17f587595bd5d3a7be56a892e3fd3a0ef83d268vboxsync * Alocate the zero page.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync rc = MMHyperAlloc(pVM, PAGE_SIZE, PAGE_SIZE, MM_TAG_PGM, &pVM->pgm.s.pvZeroPgR3);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync pVM->pgm.s.pvZeroPgRC = MMHyperR3ToRC(pVM, pVM->pgm.s.pvZeroPgR3);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync pVM->pgm.s.pvZeroPgR0 = MMHyperR3ToR0(pVM, pVM->pgm.s.pvZeroPgR3);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync pVM->pgm.s.HCPhysZeroPg = MMR3HyperHCVirt2HCPhys(pVM, pVM->pgm.s.pvZeroPgR3);
cb70d239cc25c714044be945b6f7ff4f3a8b7cdfvboxsync AssertRelease(pVM->pgm.s.HCPhysZeroPg != NIL_RTHCPHYS);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Init the paging.
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync * Init the page pool.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * Info & statistics
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync "Shows the current paging mode. "
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync "Recognizes 'all', 'guest', 'shadow' and 'host' as arguments, defaulting to 'all' if nothing's given.",
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync "Dumps all the entries in the top level paging table. No arguments.",
016bd61cdd14201a24f289559b0cc333d8c94748vboxsync "Dumps all the physical address ranges. No arguments.",
016bd61cdd14201a24f289559b0cc333d8c94748vboxsync "Dumps physical, virtual and hyper virtual handlers. "
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync "Pass 'phys', 'virt', 'hyper' as argument if only one kind is wanted."
a46e399d5426a79f6f7e18d0ba85c505280e9386vboxsync "Add 'nost' if the statistics are unwanted, use together with 'all' or explicit selection.",
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync "Dumps guest mappings.",
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync * Debugger commands.
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync static bool s_fRegisteredCmds = false;
a46e399d5426a79f6f7e18d0ba85c505280e9386vboxsync int rc2 = DBGCRegisterCommands(&g_aCmds[0], RT_ELEMENTS(g_aCmds));
13b9db9ae2c12b6c4e00eda5c79772d57a0d29e1vboxsync /* Almost no cleanup necessary, MM frees all memory. */
13b9db9ae2c12b6c4e00eda5c79772d57a0d29e1vboxsync * Initializes the per-VCPU PGM.
13b9db9ae2c12b6c4e00eda5c79772d57a0d29e1vboxsync * @returns VBox status code.
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * @param pVM The VM to operate on.
13b9db9ae2c12b6c4e00eda5c79772d57a0d29e1vboxsync * Init paging.
13b9db9ae2c12b6c4e00eda5c79772d57a0d29e1vboxsync * Since we need to check what mode the host is operating in before we can choose
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * the right paging functions for the host we have to delay this until R0 has
13b9db9ae2c12b6c4e00eda5c79772d57a0d29e1vboxsync * been initialized.
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * @returns VBox status code.
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * @param pVM VM handle.
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * Force a recalculation of modes and switcher so everyone gets notified.
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * Allocate static mapping space for whatever the cr3 register
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * points to and in the case of PAE mode to the 4 PDs.
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync int rc = MMR3HyperReserve(pVM, PAGE_SIZE * 5, "CR3 mapping", &pVM->pgm.s.GCPtrCR3Mapping);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync AssertMsgFailed(("Failed to reserve two pages for cr mapping in HMA, rc=%Rrc\n", rc));
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * Allocate pages for the three possible intermediate contexts
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * (AMD64, PAE and plain 32-Bit). We maintain all three contexts
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * for the sake of simplicity. The AMD64 uses the PAE for the
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * lower levels, making the total number of pages 11 (3 + 7 + 1).
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * We assume that two page tables will be enought for the core code
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * mappings (HC virtual and identity).
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.pInterPD = (PX86PD)MMR3PageAllocLow(pVM); AssertReturn(pVM->pgm.s.pInterPD, VERR_NO_PAGE_MEMORY);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.apInterPTs[0] = (PX86PT)MMR3PageAllocLow(pVM); AssertReturn(pVM->pgm.s.apInterPTs[0], VERR_NO_PAGE_MEMORY);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.apInterPTs[1] = (PX86PT)MMR3PageAllocLow(pVM); AssertReturn(pVM->pgm.s.apInterPTs[1], VERR_NO_PAGE_MEMORY);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.apInterPaePTs[0] = (PX86PTPAE)MMR3PageAlloc(pVM); AssertReturn(pVM->pgm.s.apInterPaePTs[0], VERR_NO_PAGE_MEMORY);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.apInterPaePTs[1] = (PX86PTPAE)MMR3PageAlloc(pVM); AssertReturn(pVM->pgm.s.apInterPaePTs[1], VERR_NO_PAGE_MEMORY);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.apInterPaePDs[0] = (PX86PDPAE)MMR3PageAlloc(pVM); AssertReturn(pVM->pgm.s.apInterPaePDs[0], VERR_NO_PAGE_MEMORY);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.apInterPaePDs[1] = (PX86PDPAE)MMR3PageAlloc(pVM); AssertReturn(pVM->pgm.s.apInterPaePDs[1], VERR_NO_PAGE_MEMORY);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.apInterPaePDs[2] = (PX86PDPAE)MMR3PageAlloc(pVM); AssertReturn(pVM->pgm.s.apInterPaePDs[2], VERR_NO_PAGE_MEMORY);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.apInterPaePDs[3] = (PX86PDPAE)MMR3PageAlloc(pVM); AssertReturn(pVM->pgm.s.apInterPaePDs[3], VERR_NO_PAGE_MEMORY);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.pInterPaePDPT = (PX86PDPT)MMR3PageAllocLow(pVM); AssertReturn(pVM->pgm.s.pInterPaePDPT, VERR_NO_PAGE_MEMORY);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.pInterPaePDPT64 = (PX86PDPT)MMR3PageAllocLow(pVM); AssertReturn(pVM->pgm.s.pInterPaePDPT64, VERR_NO_PAGE_MEMORY);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.pInterPaePML4 = (PX86PML4)MMR3PageAllocLow(pVM); AssertReturn(pVM->pgm.s.pInterPaePML4, VERR_NO_PAGE_MEMORY);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.HCPhysInterPD = MMPage2Phys(pVM, pVM->pgm.s.pInterPD);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync AssertRelease(pVM->pgm.s.HCPhysInterPD != NIL_RTHCPHYS && !(pVM->pgm.s.HCPhysInterPD & PAGE_OFFSET_MASK));
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.HCPhysInterPaePDPT = MMPage2Phys(pVM, pVM->pgm.s.pInterPaePDPT);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync AssertRelease(pVM->pgm.s.HCPhysInterPaePDPT != NIL_RTHCPHYS && !(pVM->pgm.s.HCPhysInterPaePDPT & PAGE_OFFSET_MASK));
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.HCPhysInterPaePML4 = MMPage2Phys(pVM, pVM->pgm.s.pInterPaePML4);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync AssertRelease(pVM->pgm.s.HCPhysInterPaePML4 != NIL_RTHCPHYS && !(pVM->pgm.s.HCPhysInterPaePML4 & PAGE_OFFSET_MASK) && pVM->pgm.s.HCPhysInterPaePML4 < 0xffffffff);
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * Initialize the pages, setting up the PML4 and PDPT for repetitive 4GB action.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.apInterPaePDs); i++)
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync pVM->pgm.s.pInterPaePDPT->a[i].u = X86_PDPE_P | PGM_PLXFLAGS_PERMANENT
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.pInterPaePDPT64->a); i++)
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync const unsigned iPD = i % RT_ELEMENTS(pVM->pgm.s.apInterPaePDs);
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync pVM->pgm.s.pInterPaePDPT64->a[i].u = X86_PDPE_P | X86_PDPE_RW | X86_PDPE_US | X86_PDPE_A | PGM_PLXFLAGS_PERMANENT
4584ef6026a823006bea5acbeb13dc4efe50da69vboxsync RTHCPHYS HCPhysInterPaePDPT64 = MMPage2Phys(pVM, pVM->pgm.s.pInterPaePDPT64);
9bebc668ed1ad5c93d92ff98fee1cd7dca55f6d5vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.pInterPaePML4->a); i++)
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync pVM->pgm.s.pInterPaePML4->a[i].u = X86_PML4E_P | X86_PML4E_RW | X86_PML4E_US | X86_PML4E_A | PGM_PLXFLAGS_PERMANENT
4584ef6026a823006bea5acbeb13dc4efe50da69vboxsync * Initialize paging workers and mode from current host mode
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * and the guest running in real mode.
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync AssertMsgFailed(("Host mode %d (64-bit) is not supported by non-64bit builds\n", pVM->pgm.s.enmHostMode));
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync LogRel(("Host mode %d (64-bit) is not supported by non-64bit builds\n", pVM->pgm.s.enmHostMode));
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync AssertMsgFailed(("Host mode %d is not supported\n", pVM->pgm.s.enmHostMode));
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync rc = pgmR3ModeDataInit(pVM, false /* don't resolve GC and R0 syms yet */);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync LogFlow(("pgmR3InitPaging: returns successfully\n"));
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync LogRel(("Debug: HCPhysInterPD=%RHp HCPhysInterPaePDPT=%RHp HCPhysInterPaePML4=%RHp\n",
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync pVM->pgm.s.HCPhysInterPD, pVM->pgm.s.HCPhysInterPaePDPT, pVM->pgm.s.HCPhysInterPaePML4));
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync LogRel(("Debug: apInterPTs={%RHp,%RHp} apInterPaePTs={%RHp,%RHp} apInterPaePDs={%RHp,%RHp,%RHp,%RHp} pInterPaePDPT64=%RHp\n",
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync MMPage2Phys(pVM, pVM->pgm.s.apInterPTs[0]), MMPage2Phys(pVM, pVM->pgm.s.apInterPTs[1]),
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync MMPage2Phys(pVM, pVM->pgm.s.apInterPaePTs[0]), MMPage2Phys(pVM, pVM->pgm.s.apInterPaePTs[1]),
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync MMPage2Phys(pVM, pVM->pgm.s.apInterPaePDs[0]), MMPage2Phys(pVM, pVM->pgm.s.apInterPaePDs[1]), MMPage2Phys(pVM, pVM->pgm.s.apInterPaePDs[2]), MMPage2Phys(pVM, pVM->pgm.s.apInterPaePDs[3]),
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * Init statistics
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync /* Common - misc variables */
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->cAllPages, STAMTYPE_U32, "/PGM/Page/cAllPages", STAMUNIT_COUNT, "The total number of pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->cPrivatePages, STAMTYPE_U32, "/PGM/Page/cPrivatePages", STAMUNIT_COUNT, "The number of private pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->cSharedPages, STAMTYPE_U32, "/PGM/Page/cSharedPages", STAMUNIT_COUNT, "The number of shared pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->cZeroPages, STAMTYPE_U32, "/PGM/Page/cZeroPages", STAMUNIT_COUNT, "The number of zero backed pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->cPureMmioPages, STAMTYPE_U32, "/PGM/Page/cPureMmioPages", STAMUNIT_COUNT, "The number of pure MMIO pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->cMonitoredPages, STAMTYPE_U32, "/PGM/Page/cMonitoredPages", STAMUNIT_COUNT, "The number of write monitored pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->cWrittenToPages, STAMTYPE_U32, "/PGM/Page/cWrittenToPages", STAMUNIT_COUNT, "The number of previously write monitored pages that have been written to.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->cWriteLockedPages, STAMTYPE_U32, "/PGM/Page/cWriteLockedPages", STAMUNIT_COUNT, "The number of write(/read) locked pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->cReadLockedPages, STAMTYPE_U32, "/PGM/Page/cReadLockedPages", STAMUNIT_COUNT, "The number of read (only) locked pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->cHandyPages, STAMTYPE_U32, "/PGM/Page/cHandyPages", STAMUNIT_COUNT, "The number of handy pages (not included in cAllPages).");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->cRelocations, STAMTYPE_COUNTER, "/PGM/cRelocations", STAMUNIT_OCCURENCES,"Number of hypervisor relocations.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->ChunkR3Map.c, STAMTYPE_U32, "/PGM/ChunkR3Map/c", STAMUNIT_COUNT, "Number of mapped chunks.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->ChunkR3Map.cMax, STAMTYPE_U32, "/PGM/ChunkR3Map/cMax", STAMUNIT_COUNT, "Maximum number of mapped chunks.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync /* Live save */
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.fActive, STAMTYPE_U8, "/PGM/LiveSave/fActive", STAMUNIT_COUNT, "Active or not.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.cIgnoredPages, STAMTYPE_U32, "/PGM/LiveSave/cIgnoredPages", STAMUNIT_COUNT, "The number of ignored pages in the RAM ranges (i.e. MMIO, MMIO2 and ROM).");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.cDirtyPagesLong, STAMTYPE_U32, "/PGM/LiveSave/cDirtyPagesLong", STAMUNIT_COUNT, "Longer term dirty page average.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.cDirtyPagesShort, STAMTYPE_U32, "/PGM/LiveSave/cDirtyPagesShort", STAMUNIT_COUNT, "Short term dirty page average.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.cPagesPerSecond, STAMTYPE_U32, "/PGM/LiveSave/cPagesPerSecond", STAMUNIT_COUNT, "Pages per second.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.cSavedPages, STAMTYPE_U64, "/PGM/LiveSave/cSavedPages", STAMUNIT_COUNT, "The total number of saved pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Ram.cReadyPages, STAMTYPE_U32, "/PGM/LiveSave/Ram/cReadPages", STAMUNIT_COUNT, "RAM: Ready pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Ram.cDirtyPages, STAMTYPE_U32, "/PGM/LiveSave/Ram/cDirtyPages", STAMUNIT_COUNT, "RAM: Dirty pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Ram.cZeroPages, STAMTYPE_U32, "/PGM/LiveSave/Ram/cZeroPages", STAMUNIT_COUNT, "RAM: Ready zero pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Ram.cMonitoredPages, STAMTYPE_U32, "/PGM/LiveSave/Ram/cMonitoredPages", STAMUNIT_COUNT, "RAM: Write monitored pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Rom.cReadyPages, STAMTYPE_U32, "/PGM/LiveSave/Rom/cReadPages", STAMUNIT_COUNT, "ROM: Ready pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Rom.cDirtyPages, STAMTYPE_U32, "/PGM/LiveSave/Rom/cDirtyPages", STAMUNIT_COUNT, "ROM: Dirty pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Rom.cZeroPages, STAMTYPE_U32, "/PGM/LiveSave/Rom/cZeroPages", STAMUNIT_COUNT, "ROM: Ready zero pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Rom.cMonitoredPages, STAMTYPE_U32, "/PGM/LiveSave/Rom/cMonitoredPages", STAMUNIT_COUNT, "ROM: Write monitored pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Mmio2.cReadyPages, STAMTYPE_U32, "/PGM/LiveSave/Mmio2/cReadPages", STAMUNIT_COUNT, "MMIO2: Ready pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Mmio2.cDirtyPages, STAMTYPE_U32, "/PGM/LiveSave/Mmio2/cDirtyPages", STAMUNIT_COUNT, "MMIO2: Dirty pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Mmio2.cZeroPages, STAMTYPE_U32, "/PGM/LiveSave/Mmio2/cZeroPages", STAMUNIT_COUNT, "MMIO2: Ready zero pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Mmio2.cMonitoredPages,STAMTYPE_U32, "/PGM/LiveSave/Mmio2/cMonitoredPages",STAMUNIT_COUNT, "MMIO2: Write monitored pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync# define PGM_REG_COUNTER(a, b, c) \
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync rc = STAMR3RegisterF(pVM, a, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, c, b); \
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync# define PGM_REG_COUNTER_BYTES(a, b, c) \
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync rc = STAMR3RegisterF(pVM, a, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, c, b); \
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync# define PGM_REG_PROFILE(a, b, c) \
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync rc = STAMR3RegisterF(pVM, a, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, c, b); \
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatR3DetectedConflicts, "/PGM/R3/DetectedConflicts", "The number of times PGMR3CheckMappingConflicts() detected a conflict.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPGM->StatR3ResolveConflict, "/PGM/R3/ResolveConflict", "pgmR3SyncPTResolveConflict() profiling (includes the entire relocation).");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatR3PhysRead, "/PGM/R3/Phys/Read", "The number of times PGMPhysRead was called.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatR3PhysReadBytes, "/PGM/R3/Phys/Read/Bytes", "The number of bytes read by PGMPhysRead.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatR3PhysWrite, "/PGM/R3/Phys/Write", "The number of times PGMPhysWrite was called.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatR3PhysWriteBytes, "/PGM/R3/Phys/Write/Bytes", "The number of bytes written by PGMPhysWrite.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatR3PhysSimpleRead, "/PGM/R3/Phys/Simple/Read", "The number of times PGMPhysSimpleReadGCPtr was called.");
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatR3PhysSimpleReadBytes, "/PGM/R3/Phys/Simple/Read/Bytes", "The number of bytes read by PGMPhysSimpleReadGCPtr.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatR3PhysSimpleWrite, "/PGM/R3/Phys/Simple/Write", "The number of times PGMPhysSimpleWriteGCPtr was called.");
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatR3PhysSimpleWriteBytes, "/PGM/R3/Phys/Simple/Write/Bytes", "The number of bytes written by PGMPhysSimpleWriteGCPtr.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatRZChunkR3MapTlbHits, "/PGM/ChunkR3Map/TlbHitsRZ", "TLB hits.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatRZChunkR3MapTlbMisses, "/PGM/ChunkR3Map/TlbMissesRZ", "TLB misses.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatRZPageMapTlbHits, "/PGM/RZ/Page/MapTlbHits", "TLB hits.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPGM->StatRZPageMapTlbMisses, "/PGM/RZ/Page/MapTlbMisses", "TLB misses.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPGM->StatR3ChunkR3MapTlbHits, "/PGM/ChunkR3Map/TlbHitsR3", "TLB hits.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatR3ChunkR3MapTlbMisses, "/PGM/ChunkR3Map/TlbMissesR3", "TLB misses.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatR3PageMapTlbHits, "/PGM/R3/Page/MapTlbHits", "TLB hits.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPGM->StatR3PageMapTlbMisses, "/PGM/R3/Page/MapTlbMisses", "TLB misses.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatPageMapTlbFlushes, "/PGM/R3/Page/MapTlbFlushes", "TLB flushes (all contexts).");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatPageMapTlbFlushEntry, "/PGM/R3/Page/MapTlbFlushEntry", "TLB entry flushes (all contexts).");
3ecd8008b81f02a04220705ae0033142af363280vboxsync PGM_REG_PROFILE(&pPGM->StatRZSyncCR3HandlerVirtualUpdate, "/PGM/RZ/SyncCR3/Handlers/VirtualUpdate", "Profiling of the virtual handler updates.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPGM->StatRZSyncCR3HandlerVirtualReset, "/PGM/RZ/SyncCR3/Handlers/VirtualReset", "Profiling of the virtual handler resets.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPGM->StatR3SyncCR3HandlerVirtualUpdate, "/PGM/R3/SyncCR3/Handlers/VirtualUpdate", "Profiling of the virtual handler updates.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPGM->StatR3SyncCR3HandlerVirtualReset, "/PGM/R3/SyncCR3/Handlers/VirtualReset", "Profiling of the virtual handler resets.");
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync PGM_REG_COUNTER(&pPGM->StatRZPhysHandlerReset, "/PGM/RZ/PhysHandlerReset", "The number of times PGMHandlerPhysicalReset is called.");
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync PGM_REG_COUNTER(&pPGM->StatR3PhysHandlerReset, "/PGM/R3/PhysHandlerReset", "The number of times PGMHandlerPhysicalReset is called.");
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync PGM_REG_PROFILE(&pPGM->StatRZVirtHandlerSearchByPhys, "/PGM/RZ/VirtHandlerSearchByPhys", "Profiling of pgmHandlerVirtualFindByPhysAddr.");
8ddd175fa7cb232e090f3b8934a411c167aadb27vboxsync PGM_REG_PROFILE(&pPGM->StatR3VirtHandlerSearchByPhys, "/PGM/R3/VirtHandlerSearchByPhys", "Profiling of pgmHandlerVirtualFindByPhysAddr.");
4b02cd4133ae0d8e4732c57274a59358e418349cvboxsync PGM_REG_COUNTER(&pPGM->StatRZPageReplaceShared, "/PGM/RZ/Page/ReplacedShared", "Times a shared page was replaced.");
4b02cd4133ae0d8e4732c57274a59358e418349cvboxsync PGM_REG_COUNTER(&pPGM->StatRZPageReplaceZero, "/PGM/RZ/Page/ReplacedZero", "Times the zero page was replaced.");
4b02cd4133ae0d8e4732c57274a59358e418349cvboxsync/// @todo PGM_REG_COUNTER(&pPGM->StatRZPageHandyAllocs, "/PGM/RZ/Page/HandyAllocs", "Number of times we've allocated more handy pages.");
4b02cd4133ae0d8e4732c57274a59358e418349cvboxsync PGM_REG_COUNTER(&pPGM->StatR3PageReplaceShared, "/PGM/R3/Page/ReplacedShared", "Times a shared page was replaced.");
4b02cd4133ae0d8e4732c57274a59358e418349cvboxsync PGM_REG_COUNTER(&pPGM->StatR3PageReplaceZero, "/PGM/R3/Page/ReplacedZero", "Times the zero page was replaced.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync/// @todo PGM_REG_COUNTER(&pPGM->StatR3PageHandyAllocs, "/PGM/R3/Page/HandyAllocs", "Number of times we've allocated more handy pages.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER(&pPGM->StatRZPhysRead, "/PGM/RZ/Phys/Read", "The number of times PGMPhysRead was called.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRZPhysReadBytes, "/PGM/RZ/Phys/Read/Bytes", "The number of bytes read by PGMPhysRead.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER(&pPGM->StatRZPhysWrite, "/PGM/RZ/Phys/Write", "The number of times PGMPhysWrite was called.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRZPhysWriteBytes, "/PGM/RZ/Phys/Write/Bytes", "The number of bytes written by PGMPhysWrite.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER(&pPGM->StatRZPhysSimpleRead, "/PGM/RZ/Phys/Simple/Read", "The number of times PGMPhysSimpleReadGCPtr was called.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRZPhysSimpleReadBytes, "/PGM/RZ/Phys/Simple/Read/Bytes", "The number of bytes read by PGMPhysSimpleReadGCPtr.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER(&pPGM->StatRZPhysSimpleWrite, "/PGM/RZ/Phys/Simple/Write", "The number of times PGMPhysSimpleWriteGCPtr was called.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRZPhysSimpleWriteBytes, "/PGM/RZ/Phys/Simple/Write/Bytes", "The number of bytes written by PGMPhysSimpleWriteGCPtr.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync /* GC only: */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatRCDynMapCacheHits, "/PGM/RC/DynMapCache/Hits" , "Number of dynamic page mapping cache hits.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatRCDynMapCacheMisses, "/PGM/RC/DynMapCache/Misses" , "Number of dynamic page mapping cache misses.");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync PGM_REG_COUNTER(&pPGM->StatRCInvlPgConflict, "/PGM/RC/InvlPgConflict", "Number of times PGMInvalidatePage() detected a mapping conflict.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatRCInvlPgSyncMonCR3, "/PGM/RC/InvlPgSyncMonitorCR3", "Number of times PGMInvalidatePage() ran into PGM_SYNC_MONITOR_CR3.");
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync PGM_REG_COUNTER(&pPGM->StatRCPhysRead, "/PGM/RC/Phys/Read", "The number of times PGMPhysRead was called.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRCPhysReadBytes, "/PGM/RC/Phys/Read/Bytes", "The number of bytes read by PGMPhysRead.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER(&pPGM->StatRCPhysWrite, "/PGM/RC/Phys/Write", "The number of times PGMPhysWrite was called.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRCPhysWriteBytes, "/PGM/RC/Phys/Write/Bytes", "The number of bytes written by PGMPhysWrite.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER(&pPGM->StatRCPhysSimpleRead, "/PGM/RC/Phys/Simple/Read", "The number of times PGMPhysSimpleReadGCPtr was called.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRCPhysSimpleReadBytes, "/PGM/RC/Phys/Simple/Read/Bytes", "The number of bytes read by PGMPhysSimpleReadGCPtr.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER(&pPGM->StatRCPhysSimpleWrite, "/PGM/RC/Phys/Simple/Write", "The number of times PGMPhysSimpleWriteGCPtr was called.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRCPhysSimpleWriteBytes, "/PGM/RC/Phys/Simple/Write/Bytes", "The number of bytes written by PGMPhysSimpleWriteGCPtr.");
4b02cd4133ae0d8e4732c57274a59358e418349cvboxsync PGM_REG_COUNTER(&pPGM->StatTrackVirgin, "/PGM/Track/Virgin", "The number of first time shadowings");
4b02cd4133ae0d8e4732c57274a59358e418349cvboxsync PGM_REG_COUNTER(&pPGM->StatTrackAliased, "/PGM/Track/Aliased", "The number of times switching to cRef2, i.e. the page is being shadowed by two PTs.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatTrackAliasedMany, "/PGM/Track/AliasedMany", "The number of times we're tracking using cRef2.");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync PGM_REG_COUNTER(&pPGM->StatTrackAliasedLots, "/PGM/Track/AliasedLots", "The number of times we're hitting pages which has overflowed cRef2");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatTrackOverflows, "/PGM/Track/Overflows", "The number of times the extent list grows too long.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPGM->StatTrackDeref, "/PGM/Track/Deref", "Profiling of SyncPageWorkerTrackDeref (expensive).");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync * Note! The layout below matches the member layout exactly!
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync * Common - stats
9b726ba798aabd1a27863e6f5cfeef1393bd198dvboxsync for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
9b726ba798aabd1a27863e6f5cfeef1393bd198dvboxsync#define PGM_REG_COUNTER(a, b, c) \
9b726ba798aabd1a27863e6f5cfeef1393bd198dvboxsync rc = STAMR3RegisterF(pVM, a, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, c, b, idCpu); \
9b726ba798aabd1a27863e6f5cfeef1393bd198dvboxsync#define PGM_REG_PROFILE(a, b, c) \
d9e767721ee71a4803f0de1e24f983be4faa4922vboxsync rc = STAMR3RegisterF(pVM, a, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, c, b, idCpu); \
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync PGM_REG_COUNTER(&pPgmCpu->cGuestModeChanges, "/PGM/CPU%u/cGuestModeChanges", "Number of guest mode changes.");
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync# if 0 /* rarely useful; leave for debugging. */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync for (unsigned j = 0; j < RT_ELEMENTS(pPgmCpu->StatSyncPtPD); j++)
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync STAMR3RegisterF(pVM, &pPgmCpu->StatSyncPtPD[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync "The number of SyncPT per PD n.", "/PGM/CPU%u/PDSyncPT/%04X", i, j);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync for (unsigned j = 0; j < RT_ELEMENTS(pPgmCpu->StatSyncPagePD); j++)
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync STAMR3RegisterF(pVM, &pPgmCpu->StatSyncPagePD[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync "The number of SyncPage per PD n.", "/PGM/CPU%u/PDSyncPage/%04X", i, j);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync /* R0 only: */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapMigrateInvlPg, "/PGM/CPU%u/R0/DynMapMigrateInvlPg", "invlpg count in PGMDynMapMigrateAutoSet.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatR0DynMapGCPageInl, "/PGM/CPU%u/R0/DynMapPageGCPageInl", "Calls to pgmR0DynMapGCPageInlined.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapGCPageInlHits, "/PGM/CPU%u/R0/DynMapPageGCPageInl/Hits", "Hash table lookup hits.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapGCPageInlMisses, "/PGM/CPU%u/R0/DynMapPageGCPageInl/Misses", "Misses that falls back to code common with PGMDynMapHCPage.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapGCPageInlRamHits, "/PGM/CPU%u/R0/DynMapPageGCPageInl/RamHits", "1st ram range hits.");
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapGCPageInlRamMisses, "/PGM/CPU%u/R0/DynMapPageGCPageInl/RamMisses", "1st ram range misses, takes slow path.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatR0DynMapHCPageInl, "/PGM/CPU%u/R0/DynMapPageHCPageInl", "Calls to pgmR0DynMapHCPageInlined.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapHCPageInlHits, "/PGM/CPU%u/R0/DynMapPageHCPageInl/Hits", "Hash table lookup hits.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapHCPageInlMisses, "/PGM/CPU%u/R0/DynMapPageHCPageInl/Misses", "Misses that falls back to code common with PGMDynMapHCPage.");
3ecd8008b81f02a04220705ae0033142af363280vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapPage, "/PGM/CPU%u/R0/DynMapPage", "Calls to pgmR0DynMapPage");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapSetOptimize, "/PGM/CPU%u/R0/DynMapPage/SetOptimize", "Calls to pgmDynMapOptimizeAutoSet.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapSetSearchFlushes, "/PGM/CPU%u/R0/DynMapPage/SetSearchFlushes","Set search restorting to subset flushes.");
e8f172f2032e21b4be9a8f3df20e8ef689c6a6favboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapSetSearchHits, "/PGM/CPU%u/R0/DynMapPage/SetSearchHits", "Set search hits.");
e8f172f2032e21b4be9a8f3df20e8ef689c6a6favboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapSetSearchMisses, "/PGM/CPU%u/R0/DynMapPage/SetSearchMisses", "Set search misses.");
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync PGM_REG_PROFILE(&pPgmCpu->StatR0DynMapHCPage, "/PGM/CPU%u/R0/DynMapPage/HCPage", "Calls to PGMDynMapHCPage (ring-0).");
e8f172f2032e21b4be9a8f3df20e8ef689c6a6favboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapPageHits0, "/PGM/CPU%u/R0/DynMapPage/Hits0", "Hits at iPage+0");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapPageHits1, "/PGM/CPU%u/R0/DynMapPage/Hits1", "Hits at iPage+1");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapPageHits2, "/PGM/CPU%u/R0/DynMapPage/Hits2", "Hits at iPage+2");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapPageInvlPg, "/PGM/CPU%u/R0/DynMapPage/InvlPg", "invlpg count in pgmR0DynMapPageSlow.");
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapPageSlow, "/PGM/CPU%u/R0/DynMapPage/Slow", "Calls to pgmR0DynMapPageSlow - subtract this from pgmR0DynMapPage to get 1st level hits.");
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapPageSlowLoopHits, "/PGM/CPU%u/R0/DynMapPage/SlowLoopHits" , "Hits in the loop path.");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapPageSlowLoopMisses, "/PGM/CPU%u/R0/DynMapPage/SlowLoopMisses", "Misses in the loop path. NonLoopMisses = Slow - SlowLoopHit - SlowLoopMisses");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync //PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapPageSlowLostHits, "/PGM/CPU%u/R0/DynMapPage/SlowLostHits", "Lost hits.");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapSubsets, "/PGM/CPU%u/R0/Subsets", "Times PGMDynMapPushAutoSubset was called.");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapPopFlushes, "/PGM/CPU%u/R0/SubsetPopFlushes", "Times PGMDynMapPopAutoSubset flushes the subset.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[0], "/PGM/CPU%u/R0/SetSize000..09", "00-09% filled");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[1], "/PGM/CPU%u/R0/SetSize010..19", "10-19% filled");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[2], "/PGM/CPU%u/R0/SetSize020..29", "20-29% filled");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[3], "/PGM/CPU%u/R0/SetSize030..39", "30-39% filled");
2cd06fc737773d015b5268b9e4dfba5997915957vboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[4], "/PGM/CPU%u/R0/SetSize040..49", "40-49% filled");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[5], "/PGM/CPU%u/R0/SetSize050..59", "50-59% filled");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[6], "/PGM/CPU%u/R0/SetSize060..69", "60-69% filled");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[7], "/PGM/CPU%u/R0/SetSize070..79", "70-79% filled");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[8], "/PGM/CPU%u/R0/SetSize080..89", "80-89% filled");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[9], "/PGM/CPU%u/R0/SetSize090..99", "90-99% filled");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[10], "/PGM/CPU%u/R0/SetSize100", "100% filled");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync /* RZ only: */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0e, "/PGM/CPU%u/RZ/Trap0e", "Profiling of the PGMTrap0eHandler() body.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTimeCheckPageFault, "/PGM/CPU%u/RZ/Trap0e/Time/CheckPageFault", "Profiling of checking for dirty/access emulation faults.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTimeSyncPT, "/PGM/CPU%u/RZ/Trap0e/Time/SyncPT", "Profiling of lazy page table syncing.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTimeMapping, "/PGM/CPU%u/RZ/Trap0e/Time/Mapping", "Profiling of checking virtual mappings.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTimeOutOfSync, "/PGM/CPU%u/RZ/Trap0e/Time/OutOfSync", "Profiling of out of sync page handling.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTimeHandlers, "/PGM/CPU%u/RZ/Trap0e/Time/Handlers", "Profiling of checking handlers.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2CSAM, "/PGM/CPU%u/RZ/Trap0e/Time2/CSAM", "Profiling of the Trap0eHandler body when the cause is CSAM.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2DirtyAndAccessed, "/PGM/CPU%u/RZ/Trap0e/Time2/DirtyAndAccessedBits", "Profiling of the Trap0eHandler body when the cause is dirty and/or accessed bit emulation.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2GuestTrap, "/PGM/CPU%u/RZ/Trap0e/Time2/GuestTrap", "Profiling of the Trap0eHandler body when the cause is a guest trap.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2HndPhys, "/PGM/CPU%u/RZ/Trap0e/Time2/HandlerPhysical", "Profiling of the Trap0eHandler body when the cause is a physical handler.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2HndVirt, "/PGM/CPU%u/RZ/Trap0e/Time2/HandlerVirtual", "Profiling of the Trap0eHandler body when the cause is a virtual handler.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2HndUnhandled, "/PGM/CPU%u/RZ/Trap0e/Time2/HandlerUnhandled", "Profiling of the Trap0eHandler body when the cause is access outside the monitored areas of a monitored page.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2Misc, "/PGM/CPU%u/RZ/Trap0e/Time2/Misc", "Profiling of the Trap0eHandler body when the cause is not known.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2OutOfSync, "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSync", "Profiling of the Trap0eHandler body when the cause is an out-of-sync page.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2OutOfSyncHndPhys, "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSyncHndPhys", "Profiling of the Trap0eHandler body when the cause is an out-of-sync physical handler page.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2OutOfSyncHndVirt, "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSyncHndVirt", "Profiling of the Trap0eHandler body when the cause is an out-of-sync virtual handler page.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2OutOfSyncHndObs, "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSyncObsHnd", "Profiling of the Trap0eHandler body when the cause is an obsolete handler page.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2SyncPT, "/PGM/CPU%u/RZ/Trap0e/Time2/SyncPT", "Profiling of the Trap0eHandler body when the cause is lazy syncing of a PT.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eConflicts, "/PGM/CPU%u/RZ/Trap0e/Conflicts", "The number of times #PF was caused by an undetected conflict.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eHandlersMapping, "/PGM/CPU%u/RZ/Trap0e/Handlers/Mapping", "Number of traps due to access handlers in mappings.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eHandlersOutOfSync, "/PGM/CPU%u/RZ/Trap0e/Handlers/OutOfSync", "Number of traps due to out-of-sync handled pages.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eHandlersPhysical, "/PGM/CPU%u/RZ/Trap0e/Handlers/Physical", "Number of traps due to physical access handlers.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eHandlersVirtual, "/PGM/CPU%u/RZ/Trap0e/Handlers/Virtual", "Number of traps due to virtual access handlers.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eHandlersVirtualByPhys, "/PGM/CPU%u/RZ/Trap0e/Handlers/VirtualByPhys", "Number of traps due to virtual access handlers by physical address.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eHandlersVirtualUnmarked,"/PGM/CPU%u/RZ/Trap0e/Handlers/VirtualUnmarked","Number of traps due to virtual access handlers by virtual address (without proper physical flags).");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eHandlersUnhandled, "/PGM/CPU%u/RZ/Trap0e/Handlers/Unhandled", "Number of traps due to access outside range of monitored page(s).");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eHandlersInvalid, "/PGM/CPU%u/RZ/Trap0e/Handlers/Invalid", "Number of traps due to access to invalid physical memory.");
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eUSNotPresentRead, "/PGM/CPU%u/RZ/Trap0e/Err/User/NPRead", "Number of user mode not present read page faults.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eUSNotPresentWrite, "/PGM/CPU%u/RZ/Trap0e/Err/User/NPWrite", "Number of user mode not present write page faults.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eUSWrite, "/PGM/CPU%u/RZ/Trap0e/Err/User/Write", "Number of user mode write page faults.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eUSReserved, "/PGM/CPU%u/RZ/Trap0e/Err/User/Reserved", "Number of user mode reserved bit page faults.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eUSNXE, "/PGM/CPU%u/RZ/Trap0e/Err/User/NXE", "Number of user mode NXE page faults.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eUSRead, "/PGM/CPU%u/RZ/Trap0e/Err/User/Read", "Number of user mode read page faults.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eSVNotPresentRead, "/PGM/CPU%u/RZ/Trap0e/Err/Supervisor/NPRead", "Number of supervisor mode not present read page faults.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eSVNotPresentWrite, "/PGM/CPU%u/RZ/Trap0e/Err/Supervisor/NPWrite", "Number of supervisor mode not present write page faults.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eSVWrite, "/PGM/CPU%u/RZ/Trap0e/Err/Supervisor/Write", "Number of supervisor mode write page faults.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eSVReserved, "/PGM/CPU%u/RZ/Trap0e/Err/Supervisor/Reserved", "Number of supervisor mode reserved bit page faults.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eSNXE, "/PGM/CPU%u/RZ/Trap0e/Err/Supervisor/NXE", "Number of supervisor mode NXE page faults.");
90466ec66c4fa6a8cd62f01fbf141b51189d33cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eGuestPF, "/PGM/CPU%u/RZ/Trap0e/GuestPF", "Number of real guest page faults.");
b9bd019c26def8e4d617c39121b62d7b8a826e96vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eGuestPFUnh, "/PGM/CPU%u/RZ/Trap0e/GuestPF/Unhandled", "Number of real guest page faults from the 'unhandled' case.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eGuestPFMapping, "/PGM/CPU%u/RZ/Trap0e/GuestPF/InMapping", "Number of real guest page faults in a mapping.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eWPEmulInRZ, "/PGM/CPU%u/RZ/Trap0e/WP/InRZ", "Number of guest page faults due to X86_CR0_WP emulation.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eWPEmulToR3, "/PGM/CPU%u/RZ/Trap0e/WP/ToR3", "Number of guest page faults due to X86_CR0_WP emulation (forward to R3 for emulation).");
a5c11842b92303b7b5d0086ee5011a969e321b50vboxsync#if 0 /* rarely useful; leave for debugging. */
d184d98f6e75700295aaa08ff14d0478dd6cc94avboxsync for (unsigned j = 0; j < RT_ELEMENTS(pPgmCpu->StatRZTrap0ePD); j++)
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync STAMR3RegisterF(pVM, &pPgmCpu->StatRZTrap0ePD[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
d41220dff1068effe66bb6a11f444811ba58de40vboxsync "The number of traps in page directory n.", "/PGM/CPU%u/RZ/Trap0e/PD/%04X", i, j);
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZGuestCR3WriteHandled, "/PGM/CPU%u/RZ/CR3WriteHandled", "The number of times the Guest CR3 change was successfully handled.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZGuestCR3WriteUnhandled, "/PGM/CPU%u/RZ/CR3WriteUnhandled", "The number of times the Guest CR3 change was passed back to the recompiler.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZGuestCR3WriteConflict, "/PGM/CPU%u/RZ/CR3WriteConflict", "The number of times the Guest CR3 monitoring detected a conflict.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZGuestROMWriteHandled, "/PGM/CPU%u/RZ/ROMWriteHandled", "The number of times the Guest ROM change was successfully handled.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZGuestROMWriteUnhandled, "/PGM/CPU%u/RZ/ROMWriteUnhandled", "The number of times the Guest ROM change was passed back to the recompiler.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync /* HC only: */
d41220dff1068effe66bb6a11f444811ba58de40vboxsync /* RZ & R3: */
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZSyncCR3, "/PGM/CPU%u/RZ/SyncCR3", "Profiling of the PGMSyncCR3() body.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZSyncCR3Handlers, "/PGM/CPU%u/RZ/SyncCR3/Handlers", "Profiling of the PGMSyncCR3() update handler section.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZSyncCR3Global, "/PGM/CPU%u/RZ/SyncCR3/Global", "The number of global CR3 syncs.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZSyncCR3NotGlobal, "/PGM/CPU%u/RZ/SyncCR3/NotGlobal", "The number of non-global CR3 syncs.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZSyncCR3DstCacheHit, "/PGM/CPU%u/RZ/SyncCR3/DstChacheHit", "The number of times we got some kind of a cache hit.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZSyncCR3DstFreed, "/PGM/CPU%u/RZ/SyncCR3/DstFreed", "The number of times we've had to free a shadow entry.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZSyncCR3DstFreedSrcNP, "/PGM/CPU%u/RZ/SyncCR3/DstFreedSrcNP", "The number of times we've had to free a shadow entry for which the source entry was not present.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZSyncCR3DstNotPresent, "/PGM/CPU%u/RZ/SyncCR3/DstNotPresent", "The number of times we've encountered a not present shadow entry for a present guest entry.");
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZSyncCR3DstSkippedGlobalPD, "/PGM/CPU%u/RZ/SyncCR3/DstSkippedGlobalPD", "The number of times a global page directory wasn't flushed.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZSyncCR3DstSkippedGlobalPT, "/PGM/CPU%u/RZ/SyncCR3/DstSkippedGlobalPT", "The number of times a page table with only global entries wasn't flushed.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZSyncPT, "/PGM/CPU%u/RZ/SyncPT", "Profiling of the pfnSyncPT() body.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZSyncPTFailed, "/PGM/CPU%u/RZ/SyncPT/Failed", "The number of times pfnSyncPT() failed.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZSyncPT4K, "/PGM/CPU%u/RZ/SyncPT/4K", "Nr of 4K PT syncs");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZSyncPT4M, "/PGM/CPU%u/RZ/SyncPT/4M", "Nr of 4M PT syncs");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZSyncPagePDNAs, "/PGM/CPU%u/RZ/SyncPagePDNAs", "The number of time we've marked a PD not present from SyncPage to virtualize the accessed bit.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZSyncPagePDOutOfSync, "/PGM/CPU%u/RZ/SyncPagePDOutOfSync", "The number of time we've encountered an out-of-sync PD in SyncPage.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZAccessedPage, "/PGM/CPU%u/RZ/AccessedPage", "The number of pages marked not present for accessed bit emulation.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZDirtyBitTracking, "/PGM/CPU%u/RZ/DirtyPage", "Profiling the dirty bit tracking in CheckPageFault().");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZDirtyPage, "/PGM/CPU%u/RZ/DirtyPage/Mark", "The number of pages marked read-only for dirty bit tracking.");
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZDirtyPageBig, "/PGM/CPU%u/RZ/DirtyPage/MarkBig", "The number of 4MB pages marked read-only for dirty bit tracking.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZDirtyPageSkipped, "/PGM/CPU%u/RZ/DirtyPage/Skipped", "The number of pages already dirty or readonly.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZDirtyPageTrap, "/PGM/CPU%u/RZ/DirtyPage/Trap", "The number of traps generated for dirty bit tracking.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZDirtyPageStale, "/PGM/CPU%u/RZ/DirtyPage/Stale", "The number of traps generated for dirty bit tracking (stale tlb entries).");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZDirtiedPage, "/PGM/CPU%u/RZ/DirtyPage/SetDirty", "The number of pages marked dirty because of write accesses.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZDirtyTrackRealPF, "/PGM/CPU%u/RZ/DirtyPage/RealPF", "The number of real pages faults during dirty bit tracking.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZPageAlreadyDirty, "/PGM/CPU%u/RZ/DirtyPage/AlreadySet", "The number of pages already marked dirty because of write accesses.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZInvalidatePage, "/PGM/CPU%u/RZ/InvalidatePage", "PGMInvalidatePage() profiling.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZInvalidatePage4KBPages, "/PGM/CPU%u/RZ/InvalidatePage/4KBPages", "The number of times PGMInvalidatePage() was called for a 4KB page.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZInvalidatePage4MBPages, "/PGM/CPU%u/RZ/InvalidatePage/4MBPages", "The number of times PGMInvalidatePage() was called for a 4MB page.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZInvalidatePage4MBPagesSkip, "/PGM/CPU%u/RZ/InvalidatePage/4MBPagesSkip","The number of times PGMInvalidatePage() skipped a 4MB page.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZInvalidatePagePDMappings, "/PGM/CPU%u/RZ/InvalidatePage/PDMappings", "The number of times PGMInvalidatePage() was called for a page directory containing mappings (no conflict).");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZInvalidatePagePDNAs, "/PGM/CPU%u/RZ/InvalidatePage/PDNAs", "The number of times PGMInvalidatePage() was called for a not accessed page directory.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZInvalidatePagePDNPs, "/PGM/CPU%u/RZ/InvalidatePage/PDNPs", "The number of times PGMInvalidatePage() was called for a not present page directory.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZInvalidatePagePDOutOfSync, "/PGM/CPU%u/RZ/InvalidatePage/PDOutOfSync", "The number of times PGMInvalidatePage() was called for an out of sync page directory.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZInvalidatePageSkipped, "/PGM/CPU%u/RZ/InvalidatePage/Skipped", "The number of times PGMInvalidatePage() was skipped due to not present shw or pending pending SyncCR3.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZPageOutOfSyncSupervisor, "/PGM/CPU%u/RZ/OutOfSync/SuperVisor", "Number of traps due to pages out of sync (P) and times VerifyAccessSyncPage calls SyncPage.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZPageOutOfSyncUser, "/PGM/CPU%u/RZ/OutOfSync/User", "Number of traps due to pages out of sync (P) and times VerifyAccessSyncPage calls SyncPage.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZPageOutOfSyncSupervisorWrite,"/PGM/CPU%u/RZ/OutOfSync/SuperVisorWrite", "Number of traps due to pages out of sync (RW) and times VerifyAccessSyncPage calls SyncPage.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZPageOutOfSyncUserWrite, "/PGM/CPU%u/RZ/OutOfSync/UserWrite", "Number of traps due to pages out of sync (RW) and times VerifyAccessSyncPage calls SyncPage.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZPrefetch, "/PGM/CPU%u/RZ/Prefetch", "PGMPrefetchPage profiling.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZFlushTLB, "/PGM/CPU%u/RZ/FlushTLB", "Profiling of the PGMFlushTLB() body.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZFlushTLBNewCR3, "/PGM/CPU%u/RZ/FlushTLB/NewCR3", "The number of times PGMFlushTLB was called with a new CR3, non-global. (switch)");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZFlushTLBNewCR3Global, "/PGM/CPU%u/RZ/FlushTLB/NewCR3Global", "The number of times PGMFlushTLB was called with a new CR3, global. (switch)");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZFlushTLBSameCR3, "/PGM/CPU%u/RZ/FlushTLB/SameCR3", "The number of times PGMFlushTLB was called with the same CR3, non-global. (flush)");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZFlushTLBSameCR3Global, "/PGM/CPU%u/RZ/FlushTLB/SameCR3Global", "The number of times PGMFlushTLB was called with the same CR3, global. (flush)");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZGstModifyPage, "/PGM/CPU%u/RZ/GstModifyPage", "Profiling of the PGMGstModifyPage() body.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatR3SyncCR3, "/PGM/CPU%u/R3/SyncCR3", "Profiling of the PGMSyncCR3() body.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatR3SyncCR3Handlers, "/PGM/CPU%u/R3/SyncCR3/Handlers", "Profiling of the PGMSyncCR3() update handler section.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncCR3Global, "/PGM/CPU%u/R3/SyncCR3/Global", "The number of global CR3 syncs.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncCR3NotGlobal, "/PGM/CPU%u/R3/SyncCR3/NotGlobal", "The number of non-global CR3 syncs.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncCR3DstCacheHit, "/PGM/CPU%u/R3/SyncCR3/DstChacheHit", "The number of times we got some kind of a cache hit.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncCR3DstFreed, "/PGM/CPU%u/R3/SyncCR3/DstFreed", "The number of times we've had to free a shadow entry.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncCR3DstFreedSrcNP, "/PGM/CPU%u/R3/SyncCR3/DstFreedSrcNP", "The number of times we've had to free a shadow entry for which the source entry was not present.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncCR3DstNotPresent, "/PGM/CPU%u/R3/SyncCR3/DstNotPresent", "The number of times we've encountered a not present shadow entry for a present guest entry.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncCR3DstSkippedGlobalPD, "/PGM/CPU%u/R3/SyncCR3/DstSkippedGlobalPD", "The number of times a global page directory wasn't flushed.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncCR3DstSkippedGlobalPT, "/PGM/CPU%u/R3/SyncCR3/DstSkippedGlobalPT", "The number of times a page table with only global entries wasn't flushed.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatR3SyncPT, "/PGM/CPU%u/R3/SyncPT", "Profiling of the pfnSyncPT() body.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncPTFailed, "/PGM/CPU%u/R3/SyncPT/Failed", "The number of times pfnSyncPT() failed.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncPT4K, "/PGM/CPU%u/R3/SyncPT/4K", "Nr of 4K PT syncs");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncPT4M, "/PGM/CPU%u/R3/SyncPT/4M", "Nr of 4M PT syncs");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncPagePDNAs, "/PGM/CPU%u/R3/SyncPagePDNAs", "The number of time we've marked a PD not present from SyncPage to virtualize the accessed bit.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncPagePDOutOfSync, "/PGM/CPU%u/R3/SyncPagePDOutOfSync", "The number of time we've encountered an out-of-sync PD in SyncPage.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3AccessedPage, "/PGM/CPU%u/R3/AccessedPage", "The number of pages marked not present for accessed bit emulation.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_PROFILE(&pPgmCpu->StatR3DirtyBitTracking, "/PGM/CPU%u/R3/DirtyPage", "Profiling the dirty bit tracking in CheckPageFault().");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3DirtyPage, "/PGM/CPU%u/R3/DirtyPage/Mark", "The number of pages marked read-only for dirty bit tracking.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3DirtyPageBig, "/PGM/CPU%u/R3/DirtyPage/MarkBig", "The number of 4MB pages marked read-only for dirty bit tracking.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3DirtyPageSkipped, "/PGM/CPU%u/R3/DirtyPage/Skipped", "The number of pages already dirty or readonly.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3DirtyPageTrap, "/PGM/CPU%u/R3/DirtyPage/Trap", "The number of traps generated for dirty bit tracking.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3DirtiedPage, "/PGM/CPU%u/R3/DirtyPage/SetDirty", "The number of pages marked dirty because of write accesses.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3DirtyTrackRealPF, "/PGM/CPU%u/R3/DirtyPage/RealPF", "The number of real pages faults during dirty bit tracking.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3PageAlreadyDirty, "/PGM/CPU%u/R3/DirtyPage/AlreadySet", "The number of pages already marked dirty because of write accesses.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatR3InvalidatePage, "/PGM/CPU%u/R3/InvalidatePage", "PGMInvalidatePage() profiling.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3InvalidatePage4KBPages, "/PGM/CPU%u/R3/InvalidatePage/4KBPages", "The number of times PGMInvalidatePage() was called for a 4KB page.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3InvalidatePage4MBPages, "/PGM/CPU%u/R3/InvalidatePage/4MBPages", "The number of times PGMInvalidatePage() was called for a 4MB page.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3InvalidatePage4MBPagesSkip, "/PGM/CPU%u/R3/InvalidatePage/4MBPagesSkip","The number of times PGMInvalidatePage() skipped a 4MB page.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3InvalidatePagePDMappings, "/PGM/CPU%u/R3/InvalidatePage/PDMappings", "The number of times PGMInvalidatePage() was called for a page directory containing mappings (no conflict).");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3InvalidatePagePDNAs, "/PGM/CPU%u/R3/InvalidatePage/PDNAs", "The number of times PGMInvalidatePage() was called for a not accessed page directory.");
a5c11842b92303b7b5d0086ee5011a969e321b50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3InvalidatePagePDNPs, "/PGM/CPU%u/R3/InvalidatePage/PDNPs", "The number of times PGMInvalidatePage() was called for a not present page directory.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3InvalidatePagePDOutOfSync, "/PGM/CPU%u/R3/InvalidatePage/PDOutOfSync", "The number of times PGMInvalidatePage() was called for an out of sync page directory.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3InvalidatePageSkipped, "/PGM/CPU%u/R3/InvalidatePage/Skipped", "The number of times PGMInvalidatePage() was skipped due to not present shw or pending pending SyncCR3.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3PageOutOfSyncSupervisor, "/PGM/CPU%u/R3/OutOfSync/SuperVisor", "Number of traps due to pages out of sync and times VerifyAccessSyncPage calls SyncPage.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3PageOutOfSyncUser, "/PGM/CPU%u/R3/OutOfSync/User", "Number of traps due to pages out of sync and times VerifyAccessSyncPage calls SyncPage.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_PROFILE(&pPgmCpu->StatR3Prefetch, "/PGM/CPU%u/R3/Prefetch", "PGMPrefetchPage profiling.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatR3FlushTLB, "/PGM/CPU%u/R3/FlushTLB", "Profiling of the PGMFlushTLB() body.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3FlushTLBNewCR3, "/PGM/CPU%u/R3/FlushTLB/NewCR3", "The number of times PGMFlushTLB was called with a new CR3, non-global. (switch)");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3FlushTLBNewCR3Global, "/PGM/CPU%u/R3/FlushTLB/NewCR3Global", "The number of times PGMFlushTLB was called with a new CR3, global. (switch)");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3FlushTLBSameCR3, "/PGM/CPU%u/R3/FlushTLB/SameCR3", "The number of times PGMFlushTLB was called with the same CR3, non-global. (flush)");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3FlushTLBSameCR3Global, "/PGM/CPU%u/R3/FlushTLB/SameCR3Global", "The number of times PGMFlushTLB was called with the same CR3, global. (flush)");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_PROFILE(&pPgmCpu->StatR3GstModifyPage, "/PGM/CPU%u/R3/GstModifyPage", "Profiling of the PGMGstModifyPage() body.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync#endif /* VBOX_WITH_STATISTICS */
dea1368099e5337861dd52906d4c683c447a33c4vboxsync * Init the PGM bits that rely on VMMR0 and MM to be fully initialized.
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync * The dynamic mapping area will also be allocated and initialized at this
dea1368099e5337861dd52906d4c683c447a33c4vboxsync * time. We could allocate it during PGMR3Init of course, but the mapping
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync * wouldn't be allocated at that time preventing us from setting up the
dea1368099e5337861dd52906d4c683c447a33c4vboxsync * page table entries with the dummy page.
dea1368099e5337861dd52906d4c683c447a33c4vboxsync * @returns VBox status code.
dea1368099e5337861dd52906d4c683c447a33c4vboxsync * @param pVM VM handle.
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync * Reserve space for the dynamic mappings.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = MMR3HyperReserve(pVM, MM_HYPER_DYNAMIC_SIZE, "Dynamic mapping", &GCPtr);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && (pVM->pgm.s.pbDynPageMapBaseGC >> X86_PD_PAE_SHIFT) != ((pVM->pgm.s.pbDynPageMapBaseGC + MM_HYPER_DYNAMIC_SIZE - 1) >> X86_PD_PAE_SHIFT))
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync rc = MMR3HyperReserve(pVM, MM_HYPER_DYNAMIC_SIZE, "Dynamic mapping not crossing", &GCPtr);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertRelease((pVM->pgm.s.pbDynPageMapBaseGC >> X86_PD_PAE_SHIFT) == ((pVM->pgm.s.pbDynPageMapBaseGC + MM_HYPER_DYNAMIC_SIZE - 1) >> X86_PD_PAE_SHIFT));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Ring-3 init finalizing.
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync * @returns VBox status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Reserve space for the dynamic mappings.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Initialize the dynamic mapping pages with dummy pages to simply the cache.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* get the pointer to the page table entries. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PPGMMAPPING pMapping = pgmGetMapping(pVM, pVM->pgm.s.pbDynPageMapBaseGC);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const uintptr_t off = pVM->pgm.s.pbDynPageMapBaseGC - pMapping->GCPtr;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned iPG = (off >> X86_PT_SHIFT) & X86_PT_MASK;
1e3cd9c9c95ff352da1331a1789b05fd012c880dvboxsync pVM->pgm.s.paDynPageMap32BitPTEsGC = pMapping->aPTs[iPT].pPTRC + iPG * sizeof(pMapping->aPTs[0].pPTR3->a[0]);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVM->pgm.s.paDynPageMapPaePTEsGC = pMapping->aPTs[iPT].paPaePTsRC + iPG * sizeof(pMapping->aPTs[0].paPaePTsR3->a[0]);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* init cache */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.aHCPhysDynPageMapCache); i++)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVM->pgm.s.aHCPhysDynPageMapCache[i] = HCPhysDummy;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (unsigned i = 0; i < MM_HYPER_DYNAMIC_SIZE; i += PAGE_SIZE)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGMMap(pVM, pVM->pgm.s.pbDynPageMapBaseGC + i, HCPhysDummy, PAGE_SIZE, 0);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Note that AMD uses all the 8 reserved bits for the address (so 40 bits in total);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Intel only goes up to 36 bits, so we stick to 36 as well.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo How to test for the 40 bits support? Long mode seems to be the test criterium. */
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync CPUMGetGuestCpuId(VMMGetCpu(pVM), 1, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Allocate memory if we're supposed to do that.
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync LogRel(("PGMR3InitFinalize: 4 MB PSE mask %RGp\n", pVM->pgm.s.GCPhys4MBPSEMask));
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync * Applies relocations to data and code managed by this component.
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync * This function will be called at init and whenever the VMM need to relocate it
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync * self inside the GC.
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync * @param pVM The VM.
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync * @param offDelta Relocation delta relative to old location.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncVMMR3DECL(void) PGMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync LogFlow(("PGMR3Relocate %RGv to %RGv\n", pVM->pgm.s.GCPtrCR3Mapping, pVM->pgm.s.GCPtrCR3Mapping + offDelta));
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync * Paging stuff.
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync pgmR3ModeDataInit(pVM, true /* resolve GC/R0 symbols */);
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync /* Shadow, guest and both mode switch & relocation for each VCPU. */
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync pgmR3ModeDataSwitch(pVM, pVCpu, pVCpu->pgm.s.enmShadowMode, pVCpu->pgm.s.enmGuestMode);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVM->pgm.s.pTreesRC = MMHyperR3ToRC(pVM, pVM->pgm.s.pTreesR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Ram ranges.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Update the pSelfRC pointers and relink them. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (PPGMRAMRANGE pCur = pVM->pgm.s.pRamRangesR3; pCur; pCur = pCur->pNextR3)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!(pCur->fFlags & PGM_RAM_RANGE_FLAGS_FLOATING))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Update the pSelfRC pointer of the MMIO2 ram ranges since they might not
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * be mapped and thus not included in the above exercise.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (PPGMMMIO2RANGE pCur = pVM->pgm.s.pMmio2RangesR3; pCur; pCur = pCur->pNextR3)
e85d76a7e5a047db3cdc8576ff5f412c7b73bbabvboxsync if (!(pCur->RamRange.fFlags & PGM_RAM_RANGE_FLAGS_FLOATING))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCur->RamRange.pSelfRC = MMHyperCCToRC(pVM, &pCur->RamRange);
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync * Update the two page directories with all page table mappings.
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync * (One or more of them have changed, that's why we're here.)
e85d76a7e5a047db3cdc8576ff5f412c7b73bbabvboxsync pVM->pgm.s.pMappingsRC = MMHyperR3ToRC(pVM, pVM->pgm.s.pMappingsR3);
e85d76a7e5a047db3cdc8576ff5f412c7b73bbabvboxsync for (PPGMMAPPING pCur = pVM->pgm.s.pMappingsR3; pCur->pNextR3; pCur = pCur->pNextR3)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Relocate GC addresses of Page Tables. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (PPGMMAPPING pCur = pVM->pgm.s.pMappingsR3; pCur; pCur = pCur->pNextR3)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCur->aPTs[i].pPTRC = MMHyperR3ToRC(pVM, pCur->aPTs[i].pPTR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCur->aPTs[i].paPaePTsRC = MMHyperR3ToRC(pVM, pCur->aPTs[i].paPaePTsR3);
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * Dynamic page mapping area.
10e1bc06b2908a0af56d92ffdbadd25b36a5ef61vboxsync * The Zero page.
5db1d52ffbcaa46c3d944c6c2d9c552306817d9avboxsync pVM->pgm.s.pvZeroPgR0 = MMHyperR3ToR0(pVM, pVM->pgm.s.pvZeroPgR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertRelease(pVM->pgm.s.pvZeroPgR0 != NIL_RTR0PTR || !VMMIsHwVirtExtForced(pVM));
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync AssertRelease(pVM->pgm.s.pvZeroPgR0 != NIL_RTR0PTR);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * Physical and virtual handlers.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesR3->PhysHandlers, true, pgmR3RelocatePhysHandler, &offDelta);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTAvlroGCPtrDoWithAll(&pVM->pgm.s.pTreesR3->VirtHandlers, true, pgmR3RelocateVirtHandler, &offDelta);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTAvlroGCPtrDoWithAll(&pVM->pgm.s.pTreesR3->HyperVirtHandlers, true, pgmR3RelocateHyperVirtHandler, &offDelta);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The page pool.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Callback function for relocating a physical access handler.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns 0 (continue enum)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pNode Pointer to a PGMPHYSHANDLER node.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pvUser Pointer to the offDelta. This is a pointer to the delta since we're
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * not certain the delta will fit in a void pointer for all possible configs.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsyncstatic DECLCALLBACK(int) pgmR3RelocatePhysHandler(PAVLROGCPHYSNODECORE pNode, void *pvUser)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Callback function for relocating a virtual access handler.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns 0 (continue enum)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pNode Pointer to a PGMVIRTHANDLER node.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pvUser Pointer to the offDelta. This is a pointer to the delta since we're
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * not certain the delta will fit in a void pointer for all possible configs.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(int) pgmR3RelocateVirtHandler(PAVLROGCPTRNODECORE pNode, void *pvUser)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert( pHandler->enmType == PGMVIRTHANDLERTYPE_ALL
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Callback function for relocating a virtual access handler for the hypervisor mapping.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns 0 (continue enum)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pNode Pointer to a PGMVIRTHANDLER node.
abe73d9ccf5dd90fb1e3726792c56f2556a3d702vboxsync * @param pvUser Pointer to the offDelta. This is a pointer to the delta since we're
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * not certain the delta will fit in a void pointer for all possible configs.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(int) pgmR3RelocateHyperVirtHandler(PAVLROGCPTRNODECORE pNode, void *pvUser)
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync Assert(pHandler->enmType == PGMVIRTHANDLERTYPE_HYPERVISOR);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Resets a virtual CPU when unplugged.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVCpu The virtual CPU handle.
fa7355597d7eba5b4ca8a23056ebe1b8fb306fdbvboxsyncVMMR3DECL(void) PGMR3ResetUnpluggedCpu(PVM pVM, PVMCPU pVCpu)
3a21cbe769e7500039a2d17c794a911f7acb2dadvboxsync STAM_REL_COUNTER_RESET(&pVCpu->pgm.s.cGuestModeChanges);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Re-init other members.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Clear the FFs PGM owns.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
74991d7531692858fd22acf371a7ee941567977cvboxsync * The VM is being reset.
74991d7531692858fd22acf371a7ee941567977cvboxsync * For the PGM component this means that any PD write monitors
74991d7531692858fd22acf371a7ee941567977cvboxsync * needs to be removed.
74991d7531692858fd22acf371a7ee941567977cvboxsync * @param pVM VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Unfix any fixed mappings and disable CR3 monitoring.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Exit the guest paging mode before the pgm pool gets reset.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Important to clean up the amd64 case.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Switch mode back to real mode. (before resetting the pgm pool!)
0174432b2b1a760b89840ba696f7ba51def65dddvboxsync STAM_REL_COUNTER_RESET(&pVCpu->pgm.s.cGuestModeChanges);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Reset the shadow page pool.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Re-init other members.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Clear the FFs PGM owns.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync * Reset (zero) RAM pages.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Reset (zero) shadow ROM pages.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync //return rc;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * VM state change callback for clearing fNoMorePhysWrites after
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * a snapshot has been created.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(void) pgmR3ResetNoMorePhysWritesFlag(PVM pVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Terminates the PGM.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM Pointer to VM structure.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Terminates the per-VCPU PGM.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Termination means cleaning up and freeing all resources,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the VM it self is at this point powered off or suspended.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM to operate on.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * Show paging mode.
10e1bc06b2908a0af56d92ffdbadd25b36a5ef61vboxsync * @param pVM VM Handle.
8f7bc6ad2b7bbcb4b3b96248cd2478e45f2e3b88vboxsync * @param pHlp The info helpers.
5db1d52ffbcaa46c3d944c6c2d9c552306817d9avboxsync * @param pszArgs "all" (default), "guest", "shadow" or "host".
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsyncstatic DECLCALLBACK(void) pgmR3InfoMode(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* digest argument. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!pszArgs || !*pszArgs || strstr(pszArgs, "all"))
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync /** @todo SMP support! */
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync /* print info. */
ec588a4ac8429a8b6c744544818b3ce3b2c75690vboxsync pHlp->pfnPrintf(pHlp, "Guest paging mode: %s, changed %RU64 times, A20 %s\n",
75fca099c974cbbd48f132af1378c60232614760vboxsync PGMGetModeName(pVM->aCpus[0].pgm.s.enmGuestMode), pVM->aCpus[0].pgm.s.cGuestModeChanges.c,
75fca099c974cbbd48f132af1378c60232614760vboxsync pVM->aCpus[0].pgm.s.fA20Enabled ? "enabled" : "disabled");
57f41f24b7a290eba73c63449f44017d7917561dvboxsync pHlp->pfnPrintf(pHlp, "Shadow paging mode: %s\n", PGMGetModeName(pVM->aCpus[0].pgm.s.enmShadowMode));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const char *psz;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_INVALID: psz = "invalid"; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_32_BIT_GLOBAL: psz = "32-bit+G"; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_PAE_GLOBAL: psz = "PAE+G"; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_PAE_GLOBAL_NX: psz = "PAE+G+NX"; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_AMD64_GLOBAL: psz = "AMD64+G"; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_AMD64_NX: psz = "AMD64+NX"; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case SUPPAGINGMODE_AMD64_GLOBAL_NX: psz = "AMD64+G+NX"; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHlp->pfnPrintf(pHlp, "Host paging mode: %s\n", psz);
c33db29e7b41467a35675031f5f5233839909083vboxsync * Dump registered MMIO ranges to the log.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM VM Handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pHlp The info helpers.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszArgs Arguments, ignored.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(void) pgmR3PhysInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
10e1bc06b2908a0af56d92ffdbadd25b36a5ef61vboxsync "RAM ranges (pVM=%p)\n"
315f443a509c31db47b8f5cb94d26e54c3d5c497vboxsync "%.*s %.*s\n",
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync for (PPGMRAMRANGE pCur = pVM->pgm.s.pRamRangesR3; pCur; pCur = pCur->pNextR3)
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync "%RGp-%RGp %RHv %s\n",
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync * Dump the page directory to the log.
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * @param pVM VM Handle.
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * @param pHlp The info helpers.
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * @param pszArgs Arguments, ignored.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(void) pgmR3InfoCr3(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo SMP support!! */
75fca099c974cbbd48f132af1378c60232614760vboxsync/** @todo fix this! Convert the PGMR3DumpHierarchyHC functions to do guest stuff. */
57f41f24b7a290eba73c63449f44017d7917561dvboxsync /* Big pages supported? */
a3db4ff1e0aa7f94c9176ef16264df572eec0aebvboxsync const bool fPSE = !!(CPUMGetGuestCR4(pVCpu) & X86_CR4_PSE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Global pages supported? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const bool fPGE = !!(CPUMGetGuestCR4(pVCpu) & X86_CR4_PGE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Get page directory addresses.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PX86PD pPDSrc = pgmGstGet32bitPDPtr(&pVCpu->pgm.s);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(PGMPhysGCPhys2R3PtrAssert(pVM, (RTGCPHYS)(CPUMGetGuestCR3(pVCpu) & X86_CR3_PAGE_MASK), sizeof(*pPDSrc)) == pPDSrc);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * Iterate the page directory.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync for (unsigned iPD = 0; iPD < RT_ELEMENTS(pPDSrc->a); iPD++)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%04X - %RGp P=%d U=%d RW=%d G=%d - BIG\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PdeSrc.b.u1Present, PdeSrc.b.u1User, PdeSrc.b.u1Write, PdeSrc.b.u1Global && fPGE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%04X - %RGp P=%d U=%d RW=%d [G=%d]\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PdeSrc.n.u1Present, PdeSrc.n.u1User, PdeSrc.n.u1Write, PdeSrc.b.u1Global && fPGE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Service a VMMCALLRING3_PGM_LOCK call.
32e2c6f724d4daf2665f2ffa5cbc2333073d42cfvboxsync * @returns VBox status code.
32e2c6f724d4daf2665f2ffa5cbc2333073d42cfvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = PDMR3CritSectEnterEx(&pVM->pgm.s.CritSect, true /* fHostCall */);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Converts a PGMMODE value to a PGM_TYPE_* \#define.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns PGM_TYPE_*.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pgmMode The mode value to convert.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Gets the index into the paging mode data array of a SHW+GST mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns PGM::paPagingData index.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param uShwType The shadow paging mode type.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param uGstType The guest paging mode type.
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsyncDECLINLINE(unsigned) pgmModeDataIndex(unsigned uShwType, unsigned uGstType)
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync Assert(uShwType >= PGM_TYPE_32BIT && uShwType <= PGM_TYPE_MAX);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync Assert(uGstType >= PGM_TYPE_REAL && uGstType <= PGM_TYPE_AMD64);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync return (uShwType - PGM_TYPE_32BIT) * (PGM_TYPE_AMD64 - PGM_TYPE_REAL + 1)
09881e82498fc49063e06a8896e4e16d3cffeda8vboxsync * Gets the index into the paging mode data array of a SHW+GST mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns PGM::paPagingData index.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param enmShw The shadow paging mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param enmGst The guest paging mode.
09881e82498fc49063e06a8896e4e16d3cffeda8vboxsyncDECLINLINE(unsigned) pgmModeDataIndexByMode(PGMMODE enmShw, PGMMODE enmGst)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(enmShw >= PGMMODE_32_BIT && enmShw <= PGMMODE_MAX);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(enmGst > PGMMODE_INVALID && enmGst < PGMMODE_MAX);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pgmModeDataIndex(pgmModeToType(enmShw), pgmModeToType(enmGst));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Calculates the max data index.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns The number of entries in the paging data array.
a5c11842b92303b7b5d0086ee5011a969e321b50vboxsync return pgmModeDataIndex(PGM_TYPE_MAX, PGM_TYPE_AMD64) + 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Initializes the paging mode data kept in PGM::paModeData.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fResolveGCAndR0 Indicate whether or not GC and Ring-0 symbols can be resolved now.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This is used early in the init process to avoid trouble with PDM
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * not being initialized yet.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int pgmR3ModeDataInit(PVM pVM, bool fResolveGCAndR0)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Allocate the array on the first call.
a5c11842b92303b7b5d0086ee5011a969e321b50vboxsync pVM->pgm.s.paModeData = (PPGMMODEDATA)MMR3HeapAllocZ(pVM, MM_TAG_PGM, sizeof(PGMMODEDATA) * pgmModeDataMaxIndex());
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pVM->pgm.s.paModeData, VERR_NO_MEMORY);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Initialize the array entries.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_32BIT, PGM_TYPE_REAL)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_SHW_NAME_32BIT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_32BIT_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_32BIT, PGMMODE_PROTECTED)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_SHW_NAME_32BIT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_PROT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_32BIT_PROT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_32BIT, PGM_TYPE_32BIT)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_SHW_NAME_32BIT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_32BIT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_32BIT_32BIT(InitData)(pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_PAE, PGM_TYPE_REAL)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_SHW_NAME_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_PAE_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_PAE, PGM_TYPE_PROT)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_SHW_NAME_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_PROT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_PAE_PROT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_PAE, PGM_TYPE_32BIT)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_SHW_NAME_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_32BIT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_PAE_32BIT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_PAE, PGM_TYPE_PAE)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_SHW_NAME_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_PAE_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_AMD64, PGM_TYPE_AMD64)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_SHW_NAME_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_AMD64_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* The nested paging mode. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, PGM_TYPE_REAL)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_NESTED_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, PGMMODE_PROTECTED)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_PROT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_NESTED_PROT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, PGM_TYPE_32BIT)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_32BIT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_NESTED_32BIT(InitData)(pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, PGM_TYPE_PAE)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync rc = PGM_BTH_NAME_NESTED_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, PGM_TYPE_AMD64)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync rc = PGM_BTH_NAME_NESTED_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync /* The shadow part of the nested callback mode depends on the host paging mode (AMD-V only). */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (unsigned i = PGM_TYPE_REAL; i <= PGM_TYPE_PAE; i++)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, i)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_SHW_NAME_32BIT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, PGM_TYPE_AMD64)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_SHW_NAME_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync for (unsigned i = PGM_TYPE_REAL; i <= PGM_TYPE_PAE; i++)
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, i)];
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync rc = PGM_SHW_NAME_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, PGM_TYPE_AMD64)];
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync rc = PGM_SHW_NAME_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d6b5539478863f176bfffefc1ada2b9489cfa092vboxsync#endif /* HC_ARCH_BITS == 32 */
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync for (unsigned i = PGM_TYPE_REAL; i <= PGM_TYPE_AMD64; i++)
53317612c337db70bbfc72967860b3a00021e152vboxsync for (unsigned i = PGM_TYPE_REAL; i <= PGM_TYPE_PAE; i++)
d6b5539478863f176bfffefc1ada2b9489cfa092vboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, i)];
9a99bb9ca6c5bc8ef1977e01e13b05e5cc58319bvboxsync rc = PGM_SHW_NAME_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
9c2450ffd7e8a08cc596a2e4cc4d4e4dc9b382cfvboxsync#endif /* HC_ARCH_BITS == 64 || RT_OS_DARWIN */
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync /* Extended paging (EPT) / Intel VT-x */
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_EPT, PGM_TYPE_REAL)];
016950bb1b289514e67d9e473538d22a50c0e408vboxsync rc = PGM_SHW_NAME_EPT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
9a99bb9ca6c5bc8ef1977e01e13b05e5cc58319bvboxsync rc = PGM_GST_NAME_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
9a99bb9ca6c5bc8ef1977e01e13b05e5cc58319bvboxsync rc = PGM_BTH_NAME_EPT_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
016950bb1b289514e67d9e473538d22a50c0e408vboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_EPT, PGM_TYPE_PROT)];
016950bb1b289514e67d9e473538d22a50c0e408vboxsync rc = PGM_SHW_NAME_EPT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
016950bb1b289514e67d9e473538d22a50c0e408vboxsync rc = PGM_GST_NAME_PROT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
016950bb1b289514e67d9e473538d22a50c0e408vboxsync rc = PGM_BTH_NAME_EPT_PROT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_EPT, PGM_TYPE_32BIT)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_SHW_NAME_EPT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_32BIT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_EPT_32BIT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_EPT, PGM_TYPE_PAE)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_SHW_NAME_EPT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_EPT_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_EPT, PGM_TYPE_AMD64)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_SHW_NAME_EPT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_EPT_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Switch to different (or relocated in the relocate case) mode data.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVCpu The VMCPU to operate on.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param enmShw The the shadow paging mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param enmGst The the guest paging mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic void pgmR3ModeDataSwitch(PVM pVM, PVMCPU pVCpu, PGMMODE enmShw, PGMMODE enmGst)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PPGMMODEDATA pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndexByMode(enmShw, enmGst)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pModeData->uGstType == pgmModeToType(enmGst));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pModeData->uShwType == pgmModeToType(enmShw));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* shadow */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3ShwRelocate = pModeData->pfnR3ShwRelocate;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3ShwExit = pModeData->pfnR3ShwExit;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3ShwGetPage = pModeData->pfnR3ShwGetPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3ShwModifyPage = pModeData->pfnR3ShwModifyPage;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnRCShwGetPage = pModeData->pfnRCShwGetPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnRCShwModifyPage = pModeData->pfnRCShwModifyPage;
8a132edc1577cbe2a19cd778c1b2bea6ae5e8515vboxsync pVCpu->pgm.s.pfnR0ShwGetPage = pModeData->pfnR0ShwGetPage;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnR0ShwModifyPage = pModeData->pfnR0ShwModifyPage;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync /* guest */
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnR3GstRelocate = pModeData->pfnR3GstRelocate;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnR3GstExit = pModeData->pfnR3GstExit;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnR3GstGetPage = pModeData->pfnR3GstGetPage;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnR3GstModifyPage = pModeData->pfnR3GstModifyPage;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnR3GstGetPDE = pModeData->pfnR3GstGetPDE;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnRCGstGetPage = pModeData->pfnRCGstGetPage;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnRCGstModifyPage = pModeData->pfnRCGstModifyPage;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnRCGstGetPDE = pModeData->pfnRCGstGetPDE;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnR0GstGetPage = pModeData->pfnR0GstGetPage;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnR0GstModifyPage = pModeData->pfnR0GstModifyPage;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnR0GstGetPDE = pModeData->pfnR0GstGetPDE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3BthRelocate = pModeData->pfnR3BthRelocate;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3BthInvalidatePage = pModeData->pfnR3BthInvalidatePage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3BthSyncCR3 = pModeData->pfnR3BthSyncCR3;
21d4a56532f8029ae299f552811a0b86c1909416vboxsync pVCpu->pgm.s.pfnR3BthSyncPage = pModeData->pfnR3BthSyncPage;
1a25adaca81841abf5e6cdfed02eaff64941357dvboxsync pVCpu->pgm.s.pfnR3BthPrefetchPage = pModeData->pfnR3BthPrefetchPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3BthVerifyAccessSyncPage = pModeData->pfnR3BthVerifyAccessSyncPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3BthAssertCR3 = pModeData->pfnR3BthAssertCR3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3BthMapCR3 = pModeData->pfnR3BthMapCR3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3BthUnmapCR3 = pModeData->pfnR3BthUnmapCR3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnRCBthTrap0eHandler = pModeData->pfnRCBthTrap0eHandler;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnRCBthInvalidatePage = pModeData->pfnRCBthInvalidatePage;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnRCBthSyncCR3 = pModeData->pfnRCBthSyncCR3;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnRCBthSyncPage = pModeData->pfnRCBthSyncPage;
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pVCpu->pgm.s.pfnRCBthPrefetchPage = pModeData->pfnRCBthPrefetchPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnRCBthVerifyAccessSyncPage = pModeData->pfnRCBthVerifyAccessSyncPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnRCBthAssertCR3 = pModeData->pfnRCBthAssertCR3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnRCBthMapCR3 = pModeData->pfnRCBthMapCR3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnRCBthUnmapCR3 = pModeData->pfnRCBthUnmapCR3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR0BthTrap0eHandler = pModeData->pfnR0BthTrap0eHandler;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR0BthInvalidatePage = pModeData->pfnR0BthInvalidatePage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR0BthSyncCR3 = pModeData->pfnR0BthSyncCR3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR0BthSyncPage = pModeData->pfnR0BthSyncPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR0BthPrefetchPage = pModeData->pfnR0BthPrefetchPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR0BthVerifyAccessSyncPage = pModeData->pfnR0BthVerifyAccessSyncPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR0BthAssertCR3 = pModeData->pfnR0BthAssertCR3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR0BthMapCR3 = pModeData->pfnR0BthMapCR3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR0BthUnmapCR3 = pModeData->pfnR0BthUnmapCR3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Calculates the shadow paging mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns The shadow paging mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param enmGuestMode The guest mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param enmHostMode The host mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param enmShadowMode The current shadow mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param penmSwitcher Where to store the switcher to use.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * VMMSWITCHER_INVALID means no change.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic PGMMODE pgmR3CalcShadowMode(PVM pVM, PGMMODE enmGuestMode, SUPPAGINGMODE enmHostMode, PGMMODE enmShadowMode, VMMSWITCHER *penmSwitcher)
afed5ab737f4aacfae3fe73776f40e989190a7cavboxsync * When switching to real or protected mode we don't change
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * anything since it's likely that we'll switch back pretty soon.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * During pgmR3InitPaging we'll end up here with PGMMODE_INVALID
907da3b41f191bef4c8eb94accb9d16fcbe77019vboxsync * and is supposed to determine which shadow paging and switcher to
689e03ca2c98ca6feaab8d9de6e4687a98f14ccbvboxsync * use during init.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync && !HWACCMIsEnabled(pVM) /* always switch in hwaccm mode! */)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync break; /* (no change) */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync default: AssertMsgFailed(("enmHostMode=%d\n", enmHostMode)); break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync default: AssertMsgFailed(("enmHostMode=%d\n", enmHostMode)); break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync case PGMMODE_PAE_NX: /** @todo This might require more switchers and guest+both modes. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync default: AssertMsgFailed(("enmHostMode=%d\n", enmHostMode)); break;
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync default: AssertMsgFailed(("enmHostMode=%d\n", enmHostMode)); break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReleaseMsgFailed(("enmGuestMode=%d\n", enmGuestMode));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Override the shadow mode is nested paging is active. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Performs the actual mode change.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * This is called by PGMChangeMode and pgmR3InitPaging().
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync * @returns VBox status code. May suspend or power off the VM on error, but this
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * will trigger using FFs and not status codes.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVCpu The VMCPU to operate on.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param enmGuestMode The new guest mode. This is assumed to be different from
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync * the current mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncVMMR3DECL(int) PGMR3ChangeMode(PVM pVM, PVMCPU pVCpu, PGMMODE enmGuestMode)
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync bool fIsOldGuestPagingMode64Bits = (pVCpu->pgm.s.enmGuestMode >= PGMMODE_AMD64);
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync bool fIsNewGuestPagingMode64Bits = (enmGuestMode >= PGMMODE_AMD64);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("PGMR3ChangeMode: Guest mode: %s -> %s\n", PGMGetModeName(pVCpu->pgm.s.enmGuestMode), PGMGetModeName(enmGuestMode)));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_REL_COUNTER_INC(&pVCpu->pgm.s.cGuestModeChanges);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Calc the shadow mode and switcher.
5db1d52ffbcaa46c3d944c6c2d9c552306817d9avboxsync PGMMODE enmShadowMode = pgmR3CalcShadowMode(pVM, enmGuestMode, pVM->pgm.s.enmHostMode, pVCpu->pgm.s.enmShadowMode, &enmSwitcher);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Select new switcher.
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync AssertReleaseMsgFailed(("VMMR3SelectSwitcher(%d) -> %Rrc\n", enmSwitcher, rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Exit old mode(s).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* The nested shadow paging mode for AMD-V does change when running 64 bits guests on 32 bits hosts; typically PAE <-> AMD64 */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const bool fForceShwEnterExit = ( fIsOldGuestPagingMode64Bits != fIsNewGuestPagingMode64Bits
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const bool fForceShwEnterExit = false;
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync /* shadow */
020916e230faa4a37bace3a8480f54fac94ea173vboxsync LogFlow(("PGMR3ChangeMode: Shadow mode: %s -> %s\n", PGMGetModeName(pVCpu->pgm.s.enmShadowMode), PGMGetModeName(enmShadowMode)));
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync AssertMsgFailed(("Exit failed for shadow mode %d: %Rrc\n", pVCpu->pgm.s.enmShadowMode, rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("PGMR3ChangeMode: Shadow mode remains: %s\n", PGMGetModeName(pVCpu->pgm.s.enmShadowMode)));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* guest */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Exit failed for guest mode %d: %Rrc\n", pVCpu->pgm.s.enmGuestMode, rc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Load new paging mode data.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pgmR3ModeDataSwitch(pVM, pVCpu, enmShadowMode, enmGuestMode);
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync * Enter new shadow mode (if changed).
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync rc = PGM_SHW_NAME_AMD64(Enter)(pVCpu, fIsNewGuestPagingMode64Bits);
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync rc = PGM_SHW_NAME_NESTED(Enter)(pVCpu, fIsNewGuestPagingMode64Bits);
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync rc = PGM_SHW_NAME_EPT(Enter)(pVCpu, fIsNewGuestPagingMode64Bits);
b978e5849454446957177fd47ee98609ab0457a6vboxsync AssertReleaseMsgFailed(("enmShadowMode=%d\n", enmShadowMode));
020916e230faa4a37bace3a8480f54fac94ea173vboxsync AssertReleaseMsgFailed(("Entering enmShadowMode=%d failed: %Rrc\n", enmShadowMode, rc));
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync * Always flag the necessary updates
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync * Enter the new guest and shadow+guest modes.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_GST_NAME_REAL(Enter)(pVCpu, NIL_RTGCPHYS);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc2 = PGM_BTH_NAME_32BIT_REAL(Enter)(pVCpu, NIL_RTGCPHYS);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc2 = PGM_BTH_NAME_PAE_REAL(Enter)(pVCpu, NIL_RTGCPHYS);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc2 = PGM_BTH_NAME_NESTED_REAL(Enter)(pVCpu, NIL_RTGCPHYS);
9c425bdea5f0991df62922b1584b805a86f2f898vboxsync rc2 = PGM_BTH_NAME_EPT_REAL(Enter)(pVCpu, NIL_RTGCPHYS);
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync AssertMsgFailed(("Should use PAE shadow mode!\n"));
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync default: AssertFailed(); break;
b978e5849454446957177fd47ee98609ab0457a6vboxsync rc = PGM_GST_NAME_PROT(Enter)(pVCpu, NIL_RTGCPHYS);
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync rc2 = PGM_BTH_NAME_32BIT_PROT(Enter)(pVCpu, NIL_RTGCPHYS);
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync rc2 = PGM_BTH_NAME_PAE_PROT(Enter)(pVCpu, NIL_RTGCPHYS);
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync rc2 = PGM_BTH_NAME_NESTED_PROT(Enter)(pVCpu, NIL_RTGCPHYS);
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync rc2 = PGM_BTH_NAME_EPT_PROT(Enter)(pVCpu, NIL_RTGCPHYS);
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync AssertMsgFailed(("Should use PAE shadow mode!\n"));
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync default: AssertFailed(); break;
b978e5849454446957177fd47ee98609ab0457a6vboxsync GCPhysCR3 = CPUMGetGuestCR3(pVCpu) & X86_CR3_PAGE_MASK;
020916e230faa4a37bace3a8480f54fac94ea173vboxsync rc2 = PGM_BTH_NAME_32BIT_32BIT(Enter)(pVCpu, GCPhysCR3);
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync rc2 = PGM_BTH_NAME_PAE_32BIT(Enter)(pVCpu, GCPhysCR3);
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync rc2 = PGM_BTH_NAME_NESTED_32BIT(Enter)(pVCpu, GCPhysCR3);
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync rc2 = PGM_BTH_NAME_EPT_32BIT(Enter)(pVCpu, GCPhysCR3);
b66e14ead868d803cc49957974c34c4ea47346b4vboxsync AssertMsgFailed(("Should use PAE shadow mode!\n"));
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync default: AssertFailed(); break;
020916e230faa4a37bace3a8480f54fac94ea173vboxsync CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features);
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync return VMSetRuntimeError(pVM, VMSETRTERR_FLAGS_FATAL, "PAEmode",
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync N_("The guest is trying to switch to the PAE mode which is currently disabled by default in VirtualBox. PAE support can be enabled using the VM settings (General/Advanced)"));
8c9d2065ca6efecd5661174e382314868c0d4b94vboxsync GCPhysCR3 = CPUMGetGuestCR3(pVCpu) & X86_CR3_PAE_PAGE_MASK;
1718098fb08fdb7dafd85de1aaf51debc9e72828vboxsync rc2 = PGM_BTH_NAME_PAE_PAE(Enter)(pVCpu, GCPhysCR3);
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync rc2 = PGM_BTH_NAME_NESTED_PAE(Enter)(pVCpu, GCPhysCR3);
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync rc2 = PGM_BTH_NAME_EPT_PAE(Enter)(pVCpu, GCPhysCR3);
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync AssertMsgFailed(("Should use PAE shadow mode!\n"));
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync default: AssertFailed(); break;
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync GCPhysCR3 = CPUMGetGuestCR3(pVCpu) & UINT64_C(0xfffffffffffff000); /** @todo define this mask! */
020916e230faa4a37bace3a8480f54fac94ea173vboxsync rc2 = PGM_BTH_NAME_AMD64_AMD64(Enter)(pVCpu, GCPhysCR3);
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync rc2 = PGM_BTH_NAME_NESTED_AMD64(Enter)(pVCpu, GCPhysCR3);
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync rc2 = PGM_BTH_NAME_EPT_AMD64(Enter)(pVCpu, GCPhysCR3);
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync AssertMsgFailed(("Should use AMD64 shadow mode!\n"));
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync default: AssertFailed(); break;
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync AssertReleaseMsgFailed(("enmGuestMode=%d\n", enmGuestMode));
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync /* status codes. */
020916e230faa4a37bace3a8480f54fac94ea173vboxsync if (RT_SUCCESS(rc)) /* no informational status codes. */
020916e230faa4a37bace3a8480f54fac94ea173vboxsync /* Notify HWACCM as well. */
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync HWACCMR3PagingModeChanged(pVM, pVCpu, pVCpu->pgm.s.enmShadowMode, pVCpu->pgm.s.enmGuestMode);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Release the pgm lock if owned by the current VCPU
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM to operate on.
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync * Called by pgmPoolFlushAllInt prior to flushing the pool.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code, fully asserted.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
020916e230faa4a37bace3a8480f54fac94ea173vboxsync * @param pVCpu The VMCPU to operate on.
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsyncint pgmR3ExitShadowModeBeforePoolFlush(PVM pVM, PVMCPU pVCpu)
7a6e9389a4252b9dc6fca1344e5ddbd1838849d5vboxsync /* Unmap the old CR3 value before flushing everything. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Exit the current shadow paging mode as well; nested paging and EPT use a root CR3 which will get flushed here. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Called by pgmPoolFlushAllInt after flushing the pool.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code, fully asserted.
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync * @param pVM The VM handle.
b978e5849454446957177fd47ee98609ab0457a6vboxsync * @param pVCpu The VMCPU to operate on.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncint pgmR3ReEnterShadowModeAfterPoolFlush(PVM pVM, PVMCPU pVCpu)
9424be2edf0232241bc75178b401464d4de76cadvboxsync int rc = PGMR3ChangeMode(pVM, pVCpu, PGMGetGuestMode(pVCpu));
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsync Assert(VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
b978e5849454446957177fd47ee98609ab0457a6vboxsync AssertRCSuccessReturn(rc, VERR_IPE_UNEXPECTED_INFO_STATUS);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsg( pVCpu->pgm.s.enmShadowMode >= PGMMODE_NESTED
b978e5849454446957177fd47ee98609ab0457a6vboxsync || CPUMGetHyperCR3(pVCpu) == PGMGetHyperCR3(pVCpu),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ("%RHp != %RHp %s\n", (RTHCPHYS)CPUMGetHyperCR3(pVCpu), PGMGetHyperCR3(pVCpu), PGMGetModeName(pVCpu->pgm.s.enmShadowMode)));
b978e5849454446957177fd47ee98609ab0457a6vboxsync * Dumps a PAE shadow page table.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code (VINF_SUCCESS).
020916e230faa4a37bace3a8480f54fac94ea173vboxsync * @param pVM The VM handle.
b978e5849454446957177fd47ee98609ab0457a6vboxsync * @param pPT Pointer to the page table.
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync * @param u64Address The virtual address of the page table starts.
b978e5849454446957177fd47ee98609ab0457a6vboxsync * @param fLongMode Set if this a long mode table; clear if it's a legacy mode table.
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync * @param cMaxDepth The maxium depth.
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync * @param pHlp Pointer to the output functions.
b978e5849454446957177fd47ee98609ab0457a6vboxsyncstatic int pgmR3DumpHierarchyHCPaePT(PVM pVM, PX86PTPAE pPT, uint64_t u64Address, bool fLongMode, unsigned cMaxDepth, PCDBGFINFOHLP pHlp)
b978e5849454446957177fd47ee98609ab0457a6vboxsync ? "%016llx 3 | P %c %c %c %c %c %s %s %s %s 4K %c%c%c %016llx\n"
b978e5849454446957177fd47ee98609ab0457a6vboxsync : "%08llx 2 | P %c %c %c %c %c %s %s %s %s 4K %c%c%c %016llx\n",
11c599b71a8c202a506b8623af57432c3d415ddavboxsync * Dumps a PAE shadow page directory table.
11c599b71a8c202a506b8623af57432c3d415ddavboxsync * @returns VBox status code (VINF_SUCCESS).
b978e5849454446957177fd47ee98609ab0457a6vboxsync * @param pVM The VM handle.
11c599b71a8c202a506b8623af57432c3d415ddavboxsync * @param HCPhys The physical address of the page directory table.
11c599b71a8c202a506b8623af57432c3d415ddavboxsync * @param u64Address The virtual address of the page table starts.
11c599b71a8c202a506b8623af57432c3d415ddavboxsync * @param cr4 The CR4, PSE is currently used.
11c599b71a8c202a506b8623af57432c3d415ddavboxsync * @param fLongMode Set if this a long mode table; clear if it's a legacy mode table.
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync * @param cMaxDepth The maxium depth.
11c599b71a8c202a506b8623af57432c3d415ddavboxsync * @param pHlp Pointer to the output functions.
d7f733dd34ab7755807d85016b7c2ab3d1a362d4vboxsyncstatic int pgmR3DumpHierarchyHCPaePD(PVM pVM, RTHCPHYS HCPhys, uint64_t u64Address, uint32_t cr4, bool fLongMode, unsigned cMaxDepth, PCDBGFINFOHLP pHlp)
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync PX86PDPAE pPD = (PX86PDPAE)MMPagePhys2Page(pVM, HCPhys);
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync pHlp->pfnPrintf(pHlp, "%0*llx error! Page directory at HCPhys=%RHp was not found in the page pool!\n",
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync const bool fBigPagesSupported = fLongMode || !!(cr4 & X86_CR4_PSE);
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync ? "%016llx 2 | P %c %c %c %c %c %s %s %s %s 4M %c%c%c %016llx\n"
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync : "%08llx 1 | P %c %c %c %c %c %s %s %s %s 4M %c%c%c %016llx\n",
11c599b71a8c202a506b8623af57432c3d415ddavboxsync ? "%016llx 2 | P %c %c %c %c %c %s %s .. %s 4K %c%c%c %016llx\n"
11c599b71a8c202a506b8623af57432c3d415ddavboxsync : "%08llx 1 | P %c %c %c %c %c %s %s .. %s 4K %c%c%c %016llx\n",
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync /** @todo what about using the page pool for mapping PTs? */
11c599b71a8c202a506b8623af57432c3d415ddavboxsync uint64_t u64AddressPT = u64Address + ((uint64_t)i << X86_PD_PAE_SHIFT);
b978e5849454446957177fd47ee98609ab0457a6vboxsync for (PPGMMAPPING pMap = pVM->pgm.s.pMappingsR3; pMap; pMap = pMap->pNextR3)
11c599b71a8c202a506b8623af57432c3d415ddavboxsync const int iSub = (int)((off >> X86_PD_PAE_SHIFT) & 1); /* MSC is a pain sometimes */
11c599b71a8c202a506b8623af57432c3d415ddavboxsync if ((iSub ? pMap->aPTs[iPDE].HCPhysPaePT1 : pMap->aPTs[iPDE].HCPhysPaePT0) != HCPhysPT)
11c599b71a8c202a506b8623af57432c3d415ddavboxsync pHlp->pfnPrintf(pHlp, "%0*llx error! Mapping error! PT %d has HCPhysPT=%RHp not %RHp is in the PD.\n",
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync iSub ? pMap->aPTs[iPDE].HCPhysPaePT1 : pMap->aPTs[iPDE].HCPhysPaePT0, HCPhysPT);
d6b5539478863f176bfffefc1ada2b9489cfa092vboxsync rc2 = pgmR3DumpHierarchyHCPaePT(pVM, pPT, u64AddressPT, fLongMode, cMaxDepth - 1, pHlp);
965a56f05878cf7c9634998e98d0bed41ebf21dbvboxsync pHlp->pfnPrintf(pHlp, "%0*llx error! Page table at HCPhys=%RHp was not found in the page pool!\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Dumps a PAE shadow page directory pointer table.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code (VINF_SUCCESS).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param HCPhys The physical address of the page directory pointer table.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param u64Address The virtual address of the page table starts.
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync * @param cr4 The CR4, PSE is currently used.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fLongMode Set if this a long mode table; clear if it's a legacy mode table.
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync * @param cMaxDepth The maxium depth.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pHlp Pointer to the output functions.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int pgmR3DumpHierarchyHCPaePDPT(PVM pVM, RTHCPHYS HCPhys, uint64_t u64Address, uint32_t cr4, bool fLongMode, unsigned cMaxDepth, PCDBGFINFOHLP pHlp)
bee80f3f77b15c166b7debd080a70e5231ba6751vboxsync PX86PDPT pPDPT = (PX86PDPT)MMPagePhys2Page(pVM, HCPhys);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHlp->pfnPrintf(pHlp, "%0*llx error! Page directory pointer table at HCPhys=%RHp was not found in the page pool!\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned c = fLongMode ? RT_ELEMENTS(pPDPT->a) : X86_PG_PAE_PDPE_ENTRIES;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (unsigned i = 0; i < c; i++)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHlp->pfnPrintf(pHlp, /*P R S A D G WT CD AT NX 4M a p ? */
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync "%016llx 1 | P %c %c %c %c %c %s %s %s %s .. %c%c%c %016llx\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHlp->pfnPrintf(pHlp, /*P G WT CD AT NX 4M a p ? */
9c425bdea5f0991df62922b1584b805a86f2f898vboxsync "%08x 0 | P %c %s %s %s %s .. %c%c%c %016llx\n",
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync int rc2 = pgmR3DumpHierarchyHCPaePD(pVM, Pdpe.u & X86_PDPE_PG_MASK, u64Address + ((uint64_t)i << X86_PDPT_SHIFT),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Dumps a 32-bit shadow page table.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code (VINF_SUCCESS).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
9c425bdea5f0991df62922b1584b805a86f2f898vboxsync * @param HCPhys The physical address of the table.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cr4 The CR4, PSE is currently used.
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * @param cMaxDepth The maxium depth.
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * @param pHlp Pointer to the output functions.
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsyncstatic int pgmR3DumpHierarchyHcPaePML4(PVM pVM, RTHCPHYS HCPhys, uint32_t cr4, unsigned cMaxDepth, PCDBGFINFOHLP pHlp)
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync PX86PML4 pPML4 = (PX86PML4)MMPagePhys2Page(pVM, HCPhys);
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync pHlp->pfnPrintf(pHlp, "Page map level 4 at HCPhys=%RHp was not found in the page pool!\n", HCPhys);
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pPML4->a); i++)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint64_t u64Address = ((uint64_t)i << X86_PML4_SHIFT) | (((uint64_t)i >> (X86_PML4_SHIFT - X86_PDPT_SHIFT - 1)) * 0xffff000000000000ULL);
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync pHlp->pfnPrintf(pHlp, /*P R S A D G WT CD AT NX 4M a p ? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%016llx 0 | P %c %c %c %c %c %s %s %s %s .. %c%c%c %016llx\n",
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync int rc2 = pgmR3DumpHierarchyHCPaePDPT(pVM, Pml4e.u & X86_PML4E_PG_MASK, u64Address, cr4, true, cMaxDepth - 1, pHlp);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Dumps a 32-bit shadow page table.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code (VINF_SUCCESS).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pPT Pointer to the page table.
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync * @param u32Address The virtual address this table starts at.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pHlp Pointer to the output functions.
55a158b986cee4c4ebe1a650e8727e1c6905e32evboxsyncint pgmR3DumpHierarchyHC32BitPT(PVM pVM, PX86PT pPT, uint32_t u32Address, PCDBGFINFOHLP pHlp)
55a158b986cee4c4ebe1a650e8727e1c6905e32evboxsync pHlp->pfnPrintf(pHlp, /*P R S A D G WT CD AT NX 4M a m d */
55a158b986cee4c4ebe1a650e8727e1c6905e32evboxsync "%08x 1 | P %c %c %c %c %c %s %s %s .. 4K %c%c%c %08x\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Dumps a 32-bit shadow page directory and page tables.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code (VINF_SUCCESS).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
6b022885f2cb6a55167609edecd89570cd80001dvboxsync * @param cr3 The root of the hierarchy.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cr4 The CR4, PSE is currently used.
762632a567a0397ff5d6ea93cb1fce60728e7ed3vboxsync * @param cMaxDepth How deep into the hierarchy the dumper should go.
e37007b39ddadf2af401414550b69c6c466f1633vboxsync * @param pHlp Pointer to the output functions.
f8b934f4817639cddebe4d3c2ae25d39a91fe448vboxsyncint pgmR3DumpHierarchyHC32BitPD(PVM pVM, uint32_t cr3, uint32_t cr4, unsigned cMaxDepth, PCDBGFINFOHLP pHlp)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PX86PD pPD = (PX86PD)MMPagePhys2Page(pVM, cr3 & X86_CR3_PAGE_MASK);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHlp->pfnPrintf(pHlp, "Page directory at %#x was not found in the page pool!\n", cr3 & X86_CR3_PAGE_MASK);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHlp->pfnPrintf(pHlp, /*P R S A D G WT CD AT NX 4M a m d */
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync "%08x 0 | P %c %c %c %c %c %s %s %s .. 4M %c%c%c %08x\n",
5db1d52ffbcaa46c3d944c6c2d9c552306817d9avboxsync pHlp->pfnPrintf(pHlp, /*P R S A D G WT CD AT NX 4M a m d */
da936e0446fb2b56b813d5d938f1dfc6e4bf8b13vboxsync "%08x 0 | P %c %c %c %c %c %s %s .. .. 4K %c%c%c %08x\n",
ec588a4ac8429a8b6c744544818b3ce3b2c75690vboxsync /** @todo what about using the page pool for mapping PTs? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (PPGMMAPPING pMap = pVM->pgm.s.pMappingsR3; pMap; pMap = pMap->pNextR3)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int iPDE = (u32Address - pMap->GCPtr) >> X86_PD_SHIFT;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHlp->pfnPrintf(pHlp, "%08x error! Mapping error! PT %d has HCPhysPT=%RHp not %RHp is in the PD.\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync u32Address, iPDE, pMap->aPTs[iPDE].HCPhysPT, HCPhys);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc2 = pgmR3DumpHierarchyHC32BitPT(pVM, pPT, u32Address, pHlp);
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync pHlp->pfnPrintf(pHlp, "%08x error! Page table at %#x was not found in the page pool!\n", u32Address, HCPhys);
2b88b28162a49c6fa769c03d56767a9806d4f456vboxsync * Dumps a 32-bit shadow page table.
10e1bc06b2908a0af56d92ffdbadd25b36a5ef61vboxsync * @returns VBox status code (VINF_SUCCESS).
8f7bc6ad2b7bbcb4b3b96248cd2478e45f2e3b88vboxsync * @param pVM The VM handle.
5db1d52ffbcaa46c3d944c6c2d9c552306817d9avboxsync * @param pPT Pointer to the page table.
54fe68d807196dc565de24055996e634ee40ee92vboxsync * @param u32Address The virtual address this table starts at.
54fe68d807196dc565de24055996e634ee40ee92vboxsync * @param PhysSearch Address to search for.
2b88b28162a49c6fa769c03d56767a9806d4f456vboxsyncint pgmR3DumpHierarchyGC32BitPT(PVM pVM, PX86PT pPT, uint32_t u32Address, RTGCPHYS PhysSearch)
1e3cd9c9c95ff352da1331a1789b05fd012c880dvboxsync "%08x 1 | P %c %c %c %c %c %s %s %s .. 4K %c%c%c %08x\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo SMP support!! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PGMShwGetPage(&pVM->aCpus[0], (RTGCPTR)(u32Address + (i << X86_PT_SHIFT)), &fPageShw, &pPhysHC);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("Found %RGp at %RGv -> flags=%llx\n", PhysSearch, (RTGCPTR)(u32Address + (i << X86_PT_SHIFT)), fPageShw));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Dumps a 32-bit guest page directory and page tables.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code (VINF_SUCCESS).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync * @param cr3 The root of the hierarchy.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cr4 The CR4, PSE is currently used.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param PhysSearch Address to search for.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncVMMR3DECL(int) PGMR3DumpHierarchyGC(PVM pVM, uint64_t cr3, uint64_t cr4, RTGCPHYS PhysSearch)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bool fLongMode = false;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const unsigned cch = fLongMode ? 16 : 8; NOREF(cch);
0138777a0eae9d74905d86f792f1f1c497dab65evboxsync int rc = PGM_GCPHYS_2_PTR(pVM, cr3 & X86_CR3_PAGE_MASK, &pPD);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("Page directory at %#x was not found in the page pool!\n", cr3 & X86_CR3_PAGE_MASK));
6b022885f2cb6a55167609edecd89570cd80001dvboxsync "%-*s P - Present\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | R/W - Read (0) / Write (1)\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | U/S - User (1) / Supervisor (0)\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | A - Accessed\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | D - Dirty\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | | G - Global\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | | | WT - Write thru\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | | | | CD - Cache disable\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | | | | | AT - Attribute table (PAT)\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | | | | | | NX - No execute (K8)\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | | | | | | | 4K/4M/2M - Page size.\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | | | | | | | | AVL - a=allocated; m=mapping; d=track dirty;\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | | | | | | | | | p=permanent; v=validated;\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s Level | | | | | | | | | | | | Page\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* xxxx n **** P R S A D G WT CD AT NX 4M AVL xxxxxxxxxxxxx
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync - W U - - - -- -- -- -- -- 010 */
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsync cch, "", cch, "", cch, "", cch, "", cch, "", cch, "", cch, "",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cch, "", cch, "", cch, "", cch, "", cch, "", cch, "", cch, "Address"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%08x 0 | P %c %c %c %c %c %s %s %s .. 4M %c%c%c %08x\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo PhysSearch */
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync "%08x 0 | P %c %c %c %c %c %s %s .. .. 4K %c%c%c %08x\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ////if (cMaxDepth >= 1)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo what about using the page pool for mapping PTs? */
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync rc2 = pgmR3DumpHierarchyGC32BitPT(pVM, pPT, u32Address, PhysSearch);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Log(("%08x error! Page table at %#x was not found in the page pool!\n", u32Address, GCPhys));
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync * Dumps a page table hierarchy use only physical addresses and cr4/lm flags.
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync * @returns VBox status code (VINF_SUCCESS).
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync * @param pVM The VM handle.
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync * @param cr3 The root of the hierarchy.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cr4 The cr4, only PAE and PSE is currently used.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param fLongMode Set if long mode, false if not long mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cMaxDepth Number of levels to dump.
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync * @param pHlp Pointer to the output functions.
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsyncVMMR3DECL(int) PGMR3DumpHierarchyHC(PVM pVM, uint64_t cr3, uint64_t cr4, bool fLongMode, unsigned cMaxDepth, PCDBGFINFOHLP pHlp)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "cr3=%08x cr4=%08x%s\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s P - Present\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | R/W - Read (0) / Write (1)\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | U/S - User (1) / Supervisor (0)\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | A - Accessed\n"
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync "%-*s | | | | D - Dirty\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | | G - Global\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | | | WT - Write thru\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | | | | CD - Cache disable\n"
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync "%-*s | | | | | | | | AT - Attribute table (PAT)\n"
1986f56777969a25707ab214f8dd070804be666cvboxsync "%-*s | | | | | | | | | NX - No execute (K8)\n"
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync "%-*s | | | | | | | | | | 4K/4M/2M - Page size.\n"
65ff326ac3915638f5c4e79c2c3e836aeeeb86devboxsync "%-*s | | | | | | | | | | | AVL - a=allocated; m=mapping; d=track dirty;\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | | | | | | | | | p=permanent; v=validated;\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s Level | | | | | | | | | | | | Page\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* xxxx n **** P R S A D G WT CD AT NX 4M AVL xxxxxxxxxxxxx
1986f56777969a25707ab214f8dd070804be666cvboxsync - W U - - - -- -- -- -- -- 010 */
96fb9e5765400c1ad6e462d0a25680e2312dd54cvboxsync cch, "", cch, "", cch, "", cch, "", cch, "", cch, "", cch, "",
65ff326ac3915638f5c4e79c2c3e836aeeeb86devboxsync cch, "", cch, "", cch, "", cch, "", cch, "", cch, "", cch, "Address");
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync return pgmR3DumpHierarchyHcPaePML4(pVM, cr3 & X86_CR3_PAGE_MASK, cr4, cMaxDepth, pHlp);
fa88302d5e91b79aeae01c928f33437088a90153vboxsync return pgmR3DumpHierarchyHCPaePDPT(pVM, cr3 & X86_CR3_PAE_PAGE_MASK, 0, cr4, false, cMaxDepth, pHlp);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pgmR3DumpHierarchyHC32BitPD(pVM, cr3 & X86_CR3_PAGE_MASK, cr4, cMaxDepth, pHlp);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The '.pgmram' command.
1986f56777969a25707ab214f8dd070804be666cvboxsync * @returns VBox status.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pCmd Pointer to the command descriptor (as registered).
96fb9e5765400c1ad6e462d0a25680e2312dd54cvboxsync * @param pCmdHlp Pointer to command helper functions.
65ff326ac3915638f5c4e79c2c3e836aeeeb86devboxsync * @param pVM Pointer to the current VM (if any).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param paArgs Pointer to (readonly) array of arguments.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cArgs Number of arguments in the array.
22343c7425791036f2c645cdf5316907527659b9vboxsyncstatic DECLCALLBACK(int) pgmR3CmdRam(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Sorry, no Ram is registered.\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Dump the ranges.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "From - To (incl) pvHC\n");
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync for (pRam = pVM->pgm.s.pRamRangesR3; pRam; pRam = pRam->pNextR3)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%RGp - %RGp %p\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The '.pgmerror' and '.pgmerroroff' commands.
1986f56777969a25707ab214f8dd070804be666cvboxsync * @returns VBox status.
65ff326ac3915638f5c4e79c2c3e836aeeeb86devboxsync * @param pCmd Pointer to the command descriptor (as registered).
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync * @param pCmdHlp Pointer to command helper functions.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM Pointer to the current VM (if any).
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync * @param paArgs Pointer to (readonly) array of arguments.
65ff326ac3915638f5c4e79c2c3e836aeeeb86devboxsync * @param cArgs Number of arguments in the array.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(int) pgmR3CmdError(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
ba15b5303eb3e9ebd10e3d357f51335399f9d28dvboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(cArgs == 0 || (cArgs == 1 && paArgs[0].enmType == DBGCVAR_TYPE_STRING),
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Hit bug in the parser.\n"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Print the list of error injection locations with status.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCmdHlp->pfnPrintf(pCmdHlp, NULL, "PGM error inject locations:\n");
020916e230faa4a37bace3a8480f54fac94ea173vboxsync pCmdHlp->pfnPrintf(pCmdHlp, NULL, " handy - %RTbool\n", pVM->pgm.s.fErrInjHandyPages);
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync * String switch on where to inject the error.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bool const fNewState = !strcmp(pCmd->pszCmd, "pgmerror");
65ff326ac3915638f5c4e79c2c3e836aeeeb86devboxsync ASMAtomicWriteBool(&pVM->pgm.s.fErrInjHandyPages, fNewState);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Invalid 'where' value: %s.\n", pszWhere);
6b022885f2cb6a55167609edecd89570cd80001dvboxsync * The '.pgmsync' command.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pCmd Pointer to the command descriptor (as registered).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pCmdHlp Pointer to command helper functions.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM Pointer to the current VM (if any).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param paArgs Pointer to (readonly) array of arguments.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cArgs Number of arguments in the array.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(int) pgmR3CmdSync(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync /** @todo SMP support */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Force page directory sync.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Forcing page directory sync.\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The '.pgmassertcr3' command.
bee80f3f77b15c166b7debd080a70e5231ba6751vboxsync * @returns VBox status.
65ff326ac3915638f5c4e79c2c3e836aeeeb86devboxsync * @param pCmd Pointer to the command descriptor (as registered).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pCmdHlp Pointer to command helper functions.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM Pointer to the current VM (if any).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param paArgs Pointer to (readonly) array of arguments.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cArgs Number of arguments in the array.
4668308b1dc311a789186f2fc7971394b6f26a92vboxsyncstatic DECLCALLBACK(int) pgmR3CmdAssertCR3(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo SMP support!! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Checking shadow CR3 page tables for consistency.\n");
d7f733dd34ab7755807d85016b7c2ab3d1a362d4vboxsync PGMAssertCR3(pVM, pVCpu, CPUMGetGuestCR3(pVCpu), CPUMGetGuestCR4(pVCpu));
bee80f3f77b15c166b7debd080a70e5231ba6751vboxsync#endif /* VBOX_STRICT */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The '.pgmsyncalways' command.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pCmd Pointer to the command descriptor (as registered).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pCmdHlp Pointer to command helper functions.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM Pointer to the current VM (if any).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param paArgs Pointer to (readonly) array of arguments.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cArgs Number of arguments in the array.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(int) pgmR3CmdSyncAlways(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo SMP support!! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Force page directory sync.
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync ASMAtomicAndU32(&pVCpu->pgm.s.fSyncFlags, ~PGM_SYNC_ALWAYS);
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Disabled permanent forced page directory syncing.\n");
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync ASMAtomicOrU32(&pVCpu->pgm.s.fSyncFlags, PGM_SYNC_ALWAYS);
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Enabled permanent forced page directory syncing.\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The '.pgmsyncalways' command.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status.
6f516ad9911d9037a18778742caa955fe362f8ffvboxsync * @param pCmd Pointer to the command descriptor (as registered).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pCmdHlp Pointer to command helper functions.
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync * @param pVM Pointer to the current VM (if any).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param paArgs Pointer to (readonly) array of arguments.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cArgs Number of arguments in the array.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(int) pgmR3CmdPhysToFile(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
92e770dbf167ee799d35dd505ccce02be76b85fcvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: parser error, invalid arguments.\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Invalid 2nd argument '%s', must be 'nozero'.\n", paArgs[1].u.pszString);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Open the output file and get the ram parameters.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = RTFileOpen(&hFile, paArgs[0].u.pszString, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: RTFileOpen(,'%s',) -> %Rrc.\n", paArgs[0].u.pszString, rc);
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync CFGMR3QueryU32Def(CFGMR3GetRoot(pVM), "RamHoleSize", &cbRamHole, MM_RAM_HOLE_SIZE_DEFAULT);
53163a75972769c720ae0b51a007ce4de6408778vboxsync CFGMR3QueryU64Def(CFGMR3GetRoot(pVM), "RamSize", &cbRam, 0);
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync * Dump the physical memory, page by page.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pRam && pRam->GCPhys < GCPhysEnd && RT_SUCCESS(rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* fill the gap */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTFileWrite(hFile, abZeroPg, PAGE_SIZE, NULL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync while (GCPhys < pRam->GCPhysLast && RT_SUCCESS(rc))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTFileWrite(hFile, abZeroPg, PAGE_SIZE, NULL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: RTFileWrite -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync void const *pvPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys, &pvPage, &Lock);
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: RTFileWrite -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: PGMPhysGCPhys2CCPtrReadOnly -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = RTFileWrite(hFile, abZeroPg, PAGE_SIZE, NULL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: RTFileWrite -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* advance */
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Successfully saved physical memory to '%s'.\n", paArgs[0].u.pszString);
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync#endif /* VBOX_WITH_DEBUGGER */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * pvUser argument of the pgmR3CheckIntegrity*Node callbacks.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bool fLeftToRight; /**< true: left-to-right; false: right-to-left. */
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync * Validate a node in the physical handler tree.
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync * @returns 0 on if ok, other wise 1.
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * @param pNode The handler node.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pvUser pVM.
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsyncstatic DECLCALLBACK(int) pgmR3CheckIntegrityPhysHandlerNode(PAVLROGCPHYSNODECORE pNode, void *pvUser)
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync AssertReleaseMsg(pCur->Core.Key <= pCur->Core.KeyLast,("pCur=%p %RGp-%RGp %s\n", pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync || (pArgs->fLeftToRight ? pArgs->pPrevPhys->Core.KeyLast < pCur->Core.Key : pArgs->pPrevPhys->Core.KeyLast > pCur->Core.Key),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ("pPrevPhys=%p %RGp-%RGp %s\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync " pCur=%p %RGp-%RGp %s\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pArgs->pPrevPhys, pArgs->pPrevPhys->Core.Key, pArgs->pPrevPhys->Core.KeyLast, pArgs->pPrevPhys->pszDesc,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc));
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync * Validate a node in the virtual handler tree.
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync * @returns 0 on if ok, other wise 1.
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync * @param pNode The handler node.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pvUser pVM.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(int) pgmR3CheckIntegrityVirtHandlerNode(PAVLROGCPTRNODECORE pNode, void *pvUser)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReleaseMsg(pCur->Core.Key <= pCur->Core.KeyLast,("pCur=%p %RGv-%RGv %s\n", pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync || (pArgs->fLeftToRight ? pArgs->pPrevVirt->Core.KeyLast < pCur->Core.Key : pArgs->pPrevVirt->Core.KeyLast > pCur->Core.Key),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ("pPrevVirt=%p %RGv-%RGv %s\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync " pCur=%p %RGv-%RGv %s\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pArgs->pPrevVirt, pArgs->pPrevVirt->Core.Key, pArgs->pPrevVirt->Core.KeyLast, pArgs->pPrevVirt->pszDesc,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (unsigned iPage = 0; iPage < pCur->cPages; iPage++)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReleaseMsg(pCur->aPhysToVirt[iPage].offVirtHandler == -RT_OFFSETOF(PGMVIRTHANDLER, aPhysToVirt[iPage]),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ("pCur=%p %RGv-%RGv %s\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "iPage=%d offVirtHandle=%#x expected %#x\n",
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync iPage, pCur->aPhysToVirt[iPage].offVirtHandler, -RT_OFFSETOF(PGMVIRTHANDLER, aPhysToVirt[iPage])));
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync * Validate a node in the virtual handler tree.
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * @returns 0 on if ok, other wise 1.
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync * @param pNode The handler node.
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync * @param pvUser pVM.
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsyncstatic DECLCALLBACK(int) pgmR3CheckIntegrityPhysToVirtHandlerNode(PAVLROGCPHYSNODECORE pNode, void *pvUser)
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync PPGMPHYS2VIRTHANDLER pCur = (PPGMPHYS2VIRTHANDLER)pNode;
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync AssertReleaseMsgReturn(!((uintptr_t)pCur & 3), ("\n"), 1);
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync AssertReleaseMsgReturn(!(pCur->offVirtHandler & 3), ("\n"), 1);
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync AssertReleaseMsg(pCur->Core.Key <= pCur->Core.KeyLast,("pCur=%p %RGp-%RGp\n", pCur, pCur->Core.Key, pCur->Core.KeyLast));
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync || (pArgs->fLeftToRight ? pArgs->pPrevPhys2Virt->Core.KeyLast < pCur->Core.Key : pArgs->pPrevPhys2Virt->Core.KeyLast > pCur->Core.Key),
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync ("pPrevPhys2Virt=%p %RGp-%RGp\n"
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync " pCur=%p %RGp-%RGp\n",
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync pArgs->pPrevPhys2Virt, pArgs->pPrevPhys2Virt->Core.Key, pArgs->pPrevPhys2Virt->Core.KeyLast,
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync || (pArgs->fLeftToRight ? pArgs->pPrevPhys2Virt->Core.KeyLast < pCur->Core.Key : pArgs->pPrevPhys2Virt->Core.KeyLast > pCur->Core.Key),
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync ("pPrevPhys2Virt=%p %RGp-%RGp\n"
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync " pCur=%p %RGp-%RGp\n",
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync pArgs->pPrevPhys2Virt, pArgs->pPrevPhys2Virt->Core.Key, pArgs->pPrevPhys2Virt->Core.KeyLast,
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync AssertReleaseMsg((pCur->offNextAlias & (PGMPHYS2VIRTHANDLER_IN_TREE | PGMPHYS2VIRTHANDLER_IS_HEAD)) == (PGMPHYS2VIRTHANDLER_IN_TREE | PGMPHYS2VIRTHANDLER_IS_HEAD),
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync ("pCur=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->offVirtHandler, pCur->offNextAlias));
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync if (pCur->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCur2 = (PPGMPHYS2VIRTHANDLER)((intptr_t)pCur + (pCur->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync (" pCur=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->offVirtHandler, pCur->offNextAlias));
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync AssertReleaseMsg((pCur2->offNextAlias & (PGMPHYS2VIRTHANDLER_IN_TREE | PGMPHYS2VIRTHANDLER_IS_HEAD)) == PGMPHYS2VIRTHANDLER_IN_TREE,
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync (" pCur=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n"
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync "pCur2=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->offVirtHandler, pCur->offNextAlias,
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync pCur2, pCur2->Core.Key, pCur2->Core.KeyLast, pCur2->offVirtHandler, pCur2->offNextAlias));
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync AssertReleaseMsg((pCur2->Core.Key ^ pCur->Core.Key) < PAGE_SIZE,
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync (" pCur=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n"
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync "pCur2=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->offVirtHandler, pCur->offNextAlias,
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync pCur2, pCur2->Core.Key, pCur2->Core.KeyLast, pCur2->offVirtHandler, pCur2->offNextAlias));
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync AssertReleaseMsg((pCur2->Core.KeyLast ^ pCur->Core.KeyLast) < PAGE_SIZE,
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync (" pCur=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n"
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync "pCur2=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->offVirtHandler, pCur->offNextAlias,
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync pCur2, pCur2->Core.Key, pCur2->Core.KeyLast, pCur2->offVirtHandler, pCur2->offNextAlias));
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync if (!(pCur2->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Perform an integrity check on the PGM component.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VINF_SUCCESS if everything is fine.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox error status after asserting on integrity breach.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReleaseReturn(pVM->pgm.s.offVM, VERR_INTERNAL_ERROR);
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync * Check the trees.
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync const static PGMCHECKINTARGS s_LeftToRight = { true, NULL, NULL, NULL, pVM };
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync const static PGMCHECKINTARGS s_RightToLeft = { false, NULL, NULL, NULL, pVM };
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync cErrors += RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesR3->PhysHandlers, true, pgmR3CheckIntegrityPhysHandlerNode, &Args);
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync cErrors += RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesR3->PhysHandlers, false, pgmR3CheckIntegrityPhysHandlerNode, &Args);
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync cErrors += RTAvlroGCPtrDoWithAll( &pVM->pgm.s.pTreesR3->VirtHandlers, true, pgmR3CheckIntegrityVirtHandlerNode, &Args);
34e34d3656484dde89a9c7b57fcbf7048d2fdb13vboxsync cErrors += RTAvlroGCPtrDoWithAll( &pVM->pgm.s.pTreesR3->VirtHandlers, false, pgmR3CheckIntegrityVirtHandlerNode, &Args);
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync cErrors += RTAvlroGCPtrDoWithAll( &pVM->pgm.s.pTreesR3->HyperVirtHandlers, true, pgmR3CheckIntegrityVirtHandlerNode, &Args);
34e34d3656484dde89a9c7b57fcbf7048d2fdb13vboxsync cErrors += RTAvlroGCPtrDoWithAll( &pVM->pgm.s.pTreesR3->HyperVirtHandlers, false, pgmR3CheckIntegrityVirtHandlerNode, &Args);
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync cErrors += RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesR3->PhysToVirtHandlers, true, pgmR3CheckIntegrityPhysToVirtHandlerNode, &Args);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cErrors += RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesR3->PhysToVirtHandlers, false, pgmR3CheckIntegrityPhysToVirtHandlerNode, &Args);