PGM.cpp revision 7c9a5eca233baf6ede345ace077a00bd0b7af1ef
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * PGM - Page Manager and Monitor. (Mixing stuff here, not good?)
3f1e0eea71cabeb90529e546f16eb7aee513fde9vboxsync * Copyright (C) 2006-2007 Oracle Corporation
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/** @page pg_pgm PGM - The Page Manager and Monitor
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @see grp_pgm,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @ref pg_pgm_pool,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @ref pg_pgm_phys.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @section sec_pgm_modes Paging Modes
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 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
d31ded334a29f575e23dc889b603b1a586759348vboxsync * as "host paging", and GC refered to as "shadow paging".
d31ded334a29f575e23dc889b603b1a586759348vboxsync * 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
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * depends on the host paging mode and what the mode the guest is currently in. The
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * following relation between the two is defined:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @verbatim
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Host > 32-bit | PAE | AMD64 |
2f0d866e126dd288169fed591c259c1c6b4016e5vboxsync Guest | | | |
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync ==v================================
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync 32-bit 32-bit PAE PAE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync -------|--------|--------|--------|
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PAE PAE PAE PAE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync -------|--------|--------|--------|
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AMD64 AMD64 AMD64 AMD64
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync -------|--------|--------|--------| @endverbatim
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync * All configuration except those in the diagonal (upper left) are expected to
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync * require special effort from the switcher (i.e. a bit slower).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @section sec_pgm_shw The Shadow Memory Context
614cbe11a7e5588dc8d369e223174b1441a09359vboxsync * Because of guest context mappings requires PDPT and PML4 entries to allow
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * writing on AMD64, the two upper levels will have fixed flags whatever the
614cbe11a7e5588dc8d369e223174b1441a09359vboxsync * 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
7666082b743c5e146a8cee6cc794ff4bc3fd0ffdvboxsync * ignored/reserved/MBZ). We will ignore those bits for the present.
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync * @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
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @subsection subsec_pgm_misc_diff Differences Between Legacy PAE and Long Mode PAE
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The differences between legacy PAE and long mode PAE are:
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync * -# PDPE bits 1, 2, 5 and 6 are defined differently. In leagcy mode they are
a11c569636fa6838bd423f4631a9660a5a84204bvboxsync * 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
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Placeholder.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @subsection sec_pgm_handlers_virt Virtual Access Handlers
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Placeholder.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @subsection sec_pgm_handlers_virt Virtual Access Handlers
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 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
750d4d0506a38b2e80c997075d40aad474e675fbvboxsync * 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
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * PGMHandlerVirtualRegisterEx APIs. We check for conflicting virtual handlers
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * and create a new node that is inserted into the AVL tree (range key). Then
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * a full PGM resync is flagged (clear pool, sync cr3, update virtual bit of PGMPAGE).
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync * 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
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * 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.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * PGMPHYS pages with changes will have their virtual handler state reset to NONE.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 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
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * we don't miss any alias mappings of the monitored pages.
72ef2b9fc5ffc01d0dabd5052d6e8baa3a952773vboxsync * 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.
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync * 5. The guest invalidates the page and changes the physical backing or
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * unmaps it. This should cause the invalidation callback to be invoked
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * (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.
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * We will then set all PGMPAGEs in the physical -> virtual handler cache for
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * this handler to NONE and trigger a full PGM resync (basically the same
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * as int step 1). Which means 2 is executed again.
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync * @subsubsection sub_sec_pgm_handler_virt_todo TODOs
8a132edc1577cbe2a19cd778c1b2bea6ae5e8515vboxsync * There is a bunch of things that needs to be done to make the virtual handlers
69deddbc68802f1cf1c3a404a9f816b8accb3385vboxsync * work 100% correctly and work more efficiently.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The first bit hasn't been implemented yet because it's going to slow the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * whole mess down even more, and besides it seems to be working reliably for
576d4214137bce409cdcf01e8df4a0bca5e0b2d1vboxsync * our current uses. OTOH, some of the optimizations might end up more or less
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 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
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * in mappings by means of access to them (shadow in), updates to shadows pages,
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * invlpg, and shadow PT discarding (perhaps).
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * Some idea that have popped up for optimization for current and new features:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * - bitmap indicating where there are virtual handlers installed.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * (4KB => 2**20 pages, page 2**12 => covers 32-bit address space 1:1!)
3ecd8008b81f02a04220705ae0033142af363280vboxsync * - Further optimize this by min/max (needs min/max avl getters).
3ecd8008b81f02a04220705ae0033142af363280vboxsync * - Shadow page table entry bit (if any left)?
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** @page pg_pgm_phys PGM Physical Guest Memory Management
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Objectives:
247b55faa8d054157f2481e68caca36f4dc9542cvboxsync * - Guest RAM over-commitment using memory ballooning,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * zero pages and general page sharing.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * - Moving or mirroring a VM onto a different physical machine.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * @subsection subsec_pgmPhys_Definitions Definitions
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync * Allocation chunk - A RTR0MemObjAllocPhysNC object and the tracking
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * machinery assoicated with it.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @subsection subsec_pgmPhys_AllocPage Allocating a page.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Initially we map *all* guest memory to the (per VM) zero page, which
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 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
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * be handled, but we must also make sure PGMGst*Modify doesn't make
b978e5849454446957177fd47ee98609ab0457a6vboxsync * unnecessary modifications.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Allocation points:
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * - PGMPhysSimpleWriteGCPhys and PGMPhysWrite.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * - Replacing a zero page mapping at \#PF.
247b55faa8d054157f2481e68caca36f4dc9542cvboxsync * - Replacing a shared page mapping at \#PF.
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * - ROM registration (currently MMR3RomRegister).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * - VM restore (pgmR3Load).
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * For the first three it would make sense to keep a few pages handy
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * until we've reached the max memory commitment for the VM.
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync * For the ROM registration, we know exactly how many pages we need
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * and will request these from ring-0. For restore, we will save
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * the number of non-zero pages in the saved state and allocate
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync * them up front. This would allow the ring-0 component to refuse
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync * the request if the isn't sufficient memory available for VM use.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Btw. for both ROM and restore allocations we won't be requiring
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * zeroed pages as they are going to be filled instantly.
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * @subsection subsec_pgmPhys_FreePage Freeing a page
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * There are a few points where a page can be freed:
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * - After being replaced by the zero page.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * - After being replaced by a shared page.
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * - After being ballooned by the guest additions.
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * - At reset.
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * - At restore.
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync * When freeing one or more pages they will be returned to the ring-0
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * component and replaced by the zero page.
b978e5849454446957177fd47ee98609ab0457a6vboxsync * The reasoning for clearing out all the pages on reset is that it will
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync * return us to the exact same state as on power on, and may thereby help
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * us reduce the memory load on the system. Further it might have a
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync * (temporary) positive influence on memory fragmentation (@see subsec_pgmPhys_Fragmentation).
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * On restore, as mention under the allocation topic, pages should be
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * freed / allocated depending on how many is actually required by the
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * new VM state. The simplest approach is to do like on reset, and free
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * all non-ROM pages and then allocate what we need.
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * A measure to prevent some fragmentation, would be to let each allocation
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * 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
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * our intentions and its probably not worth putting a lot of effort,
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * cpu time or memory into this.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * @subsection subsec_pgmPhys_SharePage Sharing a page
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * 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
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync * pages with the same checksum. If such pages are found, it will compare
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * them byte-by-byte to see if they actually are identical. If found to be
ebbb1f6c7e8bae363a4efda4b35b58c8467d24bcvboxsync * 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
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * VMs to use the shared page instead. If the page is all zeros (special
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * checksum and byte-by-byte check) it will request the VM that owns it
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * to replace it with the zero page.
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * To make this efficient, we will have to make sure not to try share a page
ebbb1f6c7e8bae363a4efda4b35b58c8467d24bcvboxsync * that will change its contents soon. This part requires the most work.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * 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
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * make sense to skip pages that are being write monitored since this
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * information is readily available to the thread if it works on the
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * per-VM guest memory structures (presently called PGMRAMRANGE).
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * @subsection subsec_pgmPhys_Fragmentation Fragmentation Concerns and Counter Measures
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * The pages are organized in allocation chunks in ring-0, this is a necessity
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * 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
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * become a problem as part of the idea here is that we wish to return memory to
34e34d3656484dde89a9c7b57fcbf7048d2fdb13vboxsync * the host system.
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * For instance, starting two VMs at the same time, they will both allocate the
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync * guest memory on-demand and if permitted their page allocations will be
1843553dbdf4e46417158b4c6348c503adf10740vboxsync * intermixed. Shut down one of the two VMs and it will be difficult to return
ebbb1f6c7e8bae363a4efda4b35b58c8467d24bcvboxsync * any memory to the host system because the page allocation for the two VMs are
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * mixed up in the same allocation chunks.
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * To further complicate matters, when pages are freed because they have been
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * ballooned or become shared/zero the whole idea is that the page is supposed
533ffcb943c4af2c5fe6385d816d0ba3eda9383bvboxsync * to be reused by another VM or returned to the host system. This will cause
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * allocation chunks to contain pages belonging to different VMs and prevent
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * returning memory to the host when one of those VM shuts down.
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync * The only way to really deal with this problem is to move pages. This can
e52f819639386db020b2a635b47a415248c7fbf9vboxsync * either be done at VM shutdown and or by the idle priority worker thread
b978e5849454446957177fd47ee98609ab0457a6vboxsync * that will be responsible for finding sharable/zero pages. The mechanisms
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * involved for coercing a VM to move a page (or to do it for it) will be
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the same as when telling it to share/zero a page.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * @subsection subsec_pgmPhys_Tracking Tracking Structures And Their Cost
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync * There's a difficult balance between keeping the per-page tracking structures
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * (global and guest page) easy to use and keeping them from eating too much
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * memory. We have limited virtual memory resources available when operating in
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync * 32-bit kernel space (on 64-bit there'll it's quite a different story). The
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync * tracking structures will be attemted designed such that we can deal with up
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * to 32GB of memory on a 32-bit system and essentially unlimited on 64-bit ones.
0e77737b0ba913683e614db11463b31ca67aacbevboxsync * @subsubsection subsubsec_pgmPhys_Tracking_Kernel Kernel Space
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * @see pg_GMM
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync * @subsubsection subsubsec_pgmPhys_Tracking_PerVM Per-VM
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync * Fixed info is the physical address of the page (HCPhys) and the page id
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * (described above). Theoretically we'll need 48(-12) bits for the HCPhys part.
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync * Today we've restricting ourselves to 40(-12) bits because this is the current
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * 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
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * tracking mappings of a page. 48-12 = 36. That leaves 28 bits, which means a
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * decent range for the page id: 2^(28+12) = 1024TB.
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * In additions to these, we'll have to keep maintaining the page flags as we
b74ca013e5f201a2dd371e6c438433ceac12af30vboxsync * currently do. Although it wouldn't harm to optimize these quite a bit, like
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync * for instance the ROM shouldn't depend on having a write handler installed
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync * in order for it to become read-only. A RO/RW bit should be considered so
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * that the page syncing code doesn't have to mess about checking multiple
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync * flag combinations (ROM || RW handler || write monitored) in order to
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync * figure out how to setup a shadow PTE. But this of course, is second
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * priority at present. Current this requires 12 bits, but could probably
2d53f6e472561965d363674e17f48d3bdffc24d3vboxsync * be optimized to ~8.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Then there's the 24 bits used to track which shadow page tables are
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * currently mapping a page for the purpose of speeding up physical
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * access handlers, and thereby the page pool cache. More bit for this
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync * purpose wouldn't hurt IIRC.
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync * Then there is a new bit in which we need to record what kind of page
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * this is, shared, zero, normal or write-monitored-normal. This'll
8e972b677df5ee27b99211fc7e456a5aa50f3e68vboxsync * require 2 bits. One bit might be needed for indicating whether a
8e972b677df5ee27b99211fc7e456a5aa50f3e68vboxsync * write monitored page has been written to. And yet another one or
b978e5849454446957177fd47ee98609ab0457a6vboxsync * two for tracking migration status. 3-4 bits total then.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 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
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * the idle thread will not be permitted to do modifications to it.
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * It will instead have to keep its own working set of potentially
1986f56777969a25707ab214f8dd070804be666cvboxsync * shareable pages and their check sums and stuff.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * For the present we'll keep the current packing of the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * PGMRAMRANGE::aHCPhys to keep the changes simple, only of course,
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * we'll have to change it to a struct with a total of 128-bits at
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * our disposal.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * The initial layout will be like this:
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * @verbatim
806d0b554daa555364af5f87bc96eccbe760db7avboxsync RTHCPHYS HCPhys; The current stuff.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync 63:40 Current shadow PT tracking stuff.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync 39:12 The physical page frame number.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync 11:0 The current flags.
34e34d3656484dde89a9c7b57fcbf7048d2fdb13vboxsync uint32_t u28PageId : 28; The page id.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync 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.
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync uint32_t u1Reserved : 1; Reserved for later.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync uint32_t u32Reserved; Reserved for later, mostly sharing stats.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync @endverbatim
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * The final layout will be something like this:
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * @verbatim
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTHCPHYS HCPhys; The current stuff.
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync 63:48 High page id (12+).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync 47:12 The physical page frame number.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync 11:0 Low page id.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint32_t fReadOnly : 1; Whether it's readonly page (rom or monitored in some way).
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync uint32_t u3Type : 3; The page type {RESERVED, MMIO, MMIO2, ROM, shadowed ROM, RAM}.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync 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}..
22e281e75ed636601178296c6daebda8f1d17c59vboxsync uint32_t u2State : 2; The page state { zero, shared, normal, write monitored }.
1986f56777969a25707ab214f8dd070804be666cvboxsync uint32_t fWrittenTo : 1; Whether a write monitored page was written to.
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync uint32_t u20Reserved : 20; Reserved for later, mostly sharing stats.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync uint32_t u32Tracking; The shadow PT tracking stuff, roughly.
e149c362e69e5f0bbd82da11fd8163b2d29c3a72vboxsync @endverbatim
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * Cost wise, this means we'll double the cost for guest memory. There isn't anyway
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * 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
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * example, the VM heap cost when assigning 1GB to a VM will be: 4MB.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * 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
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * 4GB guest ram, 1M pages: 16MB + 8MB(+) = 24MB
34e34d3656484dde89a9c7b57fcbf7048d2fdb13vboxsync * 32GB guest ram, 8M pages: 128MB + 64MB(+) = 192MB
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * 64-bit Windows and 64-bit linux:
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * 1GB guest ram, 256K pages: 4MB + 3MB(+) = 7MB
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync * 4GB guest ram, 1M pages: 16MB + 12MB(+) = 28MB
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * 32GB guest ram, 8M pages: 128MB + 96MB(+) = 224MB
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 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
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * than once will put the GMM off balance.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @subsection subsec_pgmPhys_Serializing Serializing Access
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Initially, we'll try a simple scheme:
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * - The per-VM RAM tracking structures (PGMRAMRANGE) is only modified
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync * 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
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the per-VM RAM tracking structures will enter the critsect.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * - No process external thread or kernel thread will ever try enter
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * the pgm critical section, as that just won't work.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * - The idle thread (and similar threads) doesn't not need 100% reliable
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * data when performing it tasks as the EMT thread will be the one to
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * do the actual changes later anyway. So, as long as it only accesses
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync * the main ram range, it can do so by somehow preventing the VM from
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync * being destroyed while it works on it...
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * - The over-commitment management, including the allocating/freeing
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * chunks, is serialized by a ring-0 mutex lock (a fast one since the
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * more mundane mutex implementation is broken on Linux).
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * - A separeate mutex is protecting the set of allocation chunks so
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * that pages can be shared or/and freed up while some other VM is
1986f56777969a25707ab214f8dd070804be666cvboxsync * allocating more chunks. This mutex can be take from under the other
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * one, but not the otherway around.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * @subsection subsec_pgmPhys_Request VM Request interface
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync * When in ring-0 it will become necessary to send requests to a VM so it can
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync * for instance move a page while defragmenting during VM destroy. The idle
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync * thread will make use of this interface to request VMs to setup shared
03319aeaef07ef63a404237f2cb56199131f4a03vboxsync * pages and to perform write monitoring of pages.
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync * I would propose an interface similar to the current VMReq interface, similar
1157941288c9533575a655c660af55d13da31eefvboxsync * in that it doesn't require locking and that the one sending the request may
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync * wait for completion if it wishes to. This shouldn't be very difficult to
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync * The requests themselves are also pretty simple. They are basically:
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * -# Check that some precondition is still true.
34e34d3656484dde89a9c7b57fcbf7048d2fdb13vboxsync * -# Do the update.
7bae75e0b207aa4d4cad2a951271ad1a0e8ab9fdvboxsync * -# Update all shadow page tables involved with the page.
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync * The 3rd step is identical to what we're already doing when updating a
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync * physical handler, see pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs.
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * @section sec_pgmPhys_MappingCaches Mapping Caches
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync * In order to be able to map in and out memory and to be able to support
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * guest with more RAM than we've got virtual address space, we'll employing
5e797edc29f96c8367de4fbf5874171c24a89ba7vboxsync * a mapping cache. There is already a tiny one for GC (see PGMGCDynMapGCPageEx)
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * and we'll create a similar one for ring-0 unless we decide to setup a dedicate
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * memory context for the HWACCM execution.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * @subsection subsec_pgmPhys_MappingCaches_R3 Ring-3
1986f56777969a25707ab214f8dd070804be666cvboxsync * We've considered implementing the ring-3 mapping cache page based but found
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * that this was bother some when one had to take into account TLBs+SMP and
e149c362e69e5f0bbd82da11fd8163b2d29c3a72vboxsync * portability (missing the necessary APIs on several platforms). There were
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * also some performance concerns with this approach which hadn't quite been
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * worked out.
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync * Instead, we'll be mapping allocation chunks into the VM process. This simplifies
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * matters greatly quite a bit since we don't need to invent any new ring-0 stuff,
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * only some minor RTR0MEMOBJ mapping stuff. The main concern here is that mapping
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync * compared to the previous idea is that mapping or unmapping a 1MB chunk is more
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync * costly than a single page, although how much more costly is uncertain. We'll
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * try address this by using a very big cache, preferably bigger than the actual
34e34d3656484dde89a9c7b57fcbf7048d2fdb13vboxsync * VM RAM size if possible. The current VM RAM sizes should give some idea for
7bae75e0b207aa4d4cad2a951271ad1a0e8ab9fdvboxsync * 32-bit boxes, while on 64-bit we can probably get away with employing an
7bae75e0b207aa4d4cad2a951271ad1a0e8ab9fdvboxsync * unlimited cache.
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync * The cache have to parts, as already indicated, the ring-3 side and the
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * ring-0 side.
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * The ring-0 will be tied to the page allocator since it will operate on the
79b24ef0ab7cd4a03a3571b3954c52ab8b573137vboxsync * memory objects it contains. It will therefore require the first ring-0 mutex
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync * discussed in @ref subsec_pgmPhys_Serializing. We
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * some double house keeping wrt to who has mapped what I think, since both
b978e5849454446957177fd47ee98609ab0457a6vboxsync * VMMR0.r0 and RTR0MemObj will keep track of mapping relataions
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync * The ring-3 part will be protected by the pgm critsect. For simplicity, we'll
7082d29724f6c3788977a51591b0379fd3acbf72vboxsync * require anyone that desires to do changes to the mapping cache to do that
7082d29724f6c3788977a51591b0379fd3acbf72vboxsync * from within this critsect. Alternatively, we could employ a separate critsect
7082d29724f6c3788977a51591b0379fd3acbf72vboxsync * for serializing changes to the mapping cache as this would reduce potential
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * contention with other threads accessing mappings unrelated to the changes
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * that are in process. We can see about this later, contention will show
46b1ac1c3302722f93e787d0f0693965e88f5ceevboxsync * up in the statistics anyway, so it'll be simple to tell.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * The organization of the ring-3 part will be very much like how the allocation
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync * chunks are organized in ring-0, that is in an AVL tree by chunk id. To avoid
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * having to walk the tree all the time, we'll have a couple of lookaside entries
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * like in we do for I/O ports and MMIO in IOM.
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * The simplified flow of a PGMPhysRead/Write function:
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * -# Enter the PGM critsect.
1986f56777969a25707ab214f8dd070804be666cvboxsync * -# Lookup GCPhys in the ram ranges and get the Page ID.
e0b9d3c357adf9b7d05f55540e86f22943fc4b23vboxsync * -# Calc the Allocation Chunk ID from the Page ID.
5cf54b3ffeb7ee90685dcaec329ef71a729f5947vboxsync * -# Check the lookaside entries and then the AVL tree for the Chunk ID.
806d0b554daa555364af5f87bc96eccbe760db7avboxsync * If not found in cache:
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * -# Call ring-0 and request it to be mapped and supply
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * a chunk to be unmapped if the cache is maxed out already.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * -# Insert the new mapping into the AVL tree (id + R3 address).
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * -# Update the relevant lookaside entry and return the mapping address.
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * -# Do the read/write according to monitoring flags and everything.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * -# Leave the critsect.
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * @section sec_pgmPhys_Fallback Fallback
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * Current all the "second tier" hosts will not support the RTR0MemObjAllocPhysNC
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * API and thus require a fallback.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * So, when RTR0MemObjAllocPhysNC returns VERR_NOT_SUPPORTED the page allocator
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * will return to the ring-3 caller (and later ring-0) and asking it to seed
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * the page allocator with some fresh pages (VERR_GMM_SEED_ME). Ring-3 will
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * then perform an SUPR3PageAlloc(cbChunk >> PAGE_SHIFT) call and make a
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync * "SeededAllocPages" call to ring-0.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * The first time ring-0 sees the VERR_NOT_SUPPORTED failure it will disable
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * 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
f9147fe1eaa4e35287f8f39282c7f92f0d7de0b7vboxsync * measures are taken to make sure that there will never be any need for
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * mapping anything into ring-3 - everything will be mapped already.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * Whether we'll continue to use the current MM locked memory management
22e281e75ed636601178296c6daebda8f1d17c59vboxsync * for this I don't quite know (I'd prefer not to and just ditch that all
1986f56777969a25707ab214f8dd070804be666cvboxsync * togther), we'll see what's simplest to do.
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync * @section sec_pgmPhys_Changes Changes
13ba5527caaa9b8c4fee29f22e374fa67c4c6f72vboxsync * Breakdown of the changes involved?
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync/*******************************************************************************
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync* Header Files *
6f0193f5a9287559d34a75f438c2682d8fb08038vboxsync*******************************************************************************/
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync/*******************************************************************************
e08de24d4792d31b7f2aac29db5cb8840d940009vboxsync* Internal Functions *
22e281e75ed636601178296c6daebda8f1d17c59vboxsync*******************************************************************************/
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsyncstatic DECLCALLBACK(void) pgmR3PhysInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsyncstatic DECLCALLBACK(void) pgmR3InfoMode(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsyncstatic DECLCALLBACK(void) pgmR3InfoCr3(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
22e281e75ed636601178296c6daebda8f1d17c59vboxsyncstatic DECLCALLBACK(int) pgmR3RelocatePhysHandler(PAVLROGCPHYSNODECORE pNode, void *pvUser);
34e34d3656484dde89a9c7b57fcbf7048d2fdb13vboxsyncstatic DECLCALLBACK(int) pgmR3RelocateVirtHandler(PAVLROGCPTRNODECORE pNode, void *pvUser);
8e8844a522f5d335f177a0313b03067d79cce201vboxsyncstatic DECLCALLBACK(int) pgmR3RelocateHyperVirtHandler(PAVLROGCPTRNODECORE pNode, void *pvUser);
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsyncstatic DECLCALLBACK(void) pgmR3ResetNoMorePhysWritesFlag(PVM pVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser);
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsyncstatic int pgmR3ModeDataInit(PVM pVM, bool fResolveGCAndR0);
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsyncstatic void pgmR3ModeDataSwitch(PVM pVM, PVMCPU pVCpu, PGMMODE enmShw, PGMMODE enmGst);
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsyncstatic PGMMODE pgmR3CalcShadowMode(PVM pVM, PGMMODE enmGuestMode, SUPPAGINGMODE enmHostMode, PGMMODE enmShadowMode, VMMSWITCHER *penmSwitcher);
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync/** @todo Convert the first two commands to 'info' items. */
b978e5849454446957177fd47ee98609ab0457a6vboxsyncstatic DECLCALLBACK(int) pgmR3CmdRam(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsyncstatic DECLCALLBACK(int) pgmR3CmdError(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsyncstatic DECLCALLBACK(int) pgmR3CmdSync(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsyncstatic DECLCALLBACK(int) pgmR3CmdSyncAlways(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsyncstatic DECLCALLBACK(int) pgmR3CmdAssertCR3(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
ce2d2eef2525963979102e63c2419d1c69d767ccvboxsyncstatic DECLCALLBACK(int) pgmR3CmdPhysToFile(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult);
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync/*******************************************************************************
ce2d2eef2525963979102e63c2419d1c69d767ccvboxsync* Global Variables *
ce2d2eef2525963979102e63c2419d1c69d767ccvboxsync*******************************************************************************/
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync/** Argument descriptors for '.pgmerror' and '.pgmerroroff'. */
ce2d2eef2525963979102e63c2419d1c69d767ccvboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
3dde2f85d4cf477621a3128887a2c08a8bca7c01vboxsync { 0, 1, DBGCVAR_CAT_STRING, 0, "where", "Error injection location." },
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync { 1, 1, DBGCVAR_CAT_STRING, 0, "file", "The file name." },
46df4404c8dbbf3672e7aae8cd0b2770356e5b73vboxsync { 0, 1, DBGCVAR_CAT_STRING, 0, "nozero", "If present, zero pages are skipped." },
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync/** Command descriptors. */
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync /* pszCmd, cArgsMin, cArgsMax, paArgDesc, cArgDescs, pResultDesc, fFlags, pfnHandler pszSyntax, ....pszDescription */
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync { "pgmram", 0, 0, NULL, 0, NULL, 0, pgmR3CmdRam, "", "Display the ram ranges." },
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync { "pgmsync", 0, 0, NULL, 0, NULL, 0, pgmR3CmdSync, "", "Sync the CR3 page." },
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync { "pgmerror", 0, 1, &g_aPgmErrorArgs[0], 1, NULL, 0, pgmR3CmdError, "", "Enables inject runtime of errors into parts of PGM." },
ce2d2eef2525963979102e63c2419d1c69d767ccvboxsync { "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." },
4b8fcf8e4d11536879a1f6e66279ba0c363a7eaevboxsync { "pgmcheckduppages", 0, 0, NULL, 0, NULL, 0, pgmR3CmdCheckDuplicatePages, "", "Check for duplicate pages in all running VMs." },
ce2d2eef2525963979102e63c2419d1c69d767ccvboxsync { "pgmsharedmodules", 0, 0, NULL, 0, NULL, 0, pgmR3CmdShowSharedModules, "", "Print shared modules info." },
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync { "pgmsyncalways", 0, 0, NULL, 0, NULL, 0, pgmR3CmdSyncAlways, "", "Toggle permanent CR3 syncing." },
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync { "pgmphystofile", 1, 2, &g_aPgmPhysToFileArgs[0], 2, NULL, 0, pgmR3CmdPhysToFile, "", "Save the physical memory to file." },
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * Shadow - 32-bit mode
65b61798a61dd4c32cce448db1dac70bba8d5cf5vboxsync#define PGM_SHW_NAME_RC_STR(name) PGM_SHW_NAME_RC_32BIT_STR(name)
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync#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)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#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
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#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)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#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
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_32BIT_PD_PHYS
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* 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)
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync#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)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_32BIT_PT_FOR_32BIT_PT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_32BIT_PT_FOR_32BIT_4MB
e17bd6c32a8dd64f2d42838f9028216465e2caf0vboxsync * Shadow - PAE mode
5ace91141404400247438502a84a418fba00c8cfvboxsync#define PGM_SHW_NAME_RC_STR(name) PGM_SHW_NAME_RC_PAE_STR(name)
5ace91141404400247438502a84a418fba00c8cfvboxsync#define PGM_SHW_NAME_R0_STR(name) PGM_SHW_NAME_R0_PAE_STR(name)
5ace91141404400247438502a84a418fba00c8cfvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_REAL(name)
49748bb305bd71f672cd083af208f4bb08c5d6abvboxsync/* Guest - real mode */
49748bb305bd71f672cd083af208f4bb08c5d6abvboxsync#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_PAE_REAL(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_PAE_REAL_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_PAE_REAL_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_PAE_PDPT_PHYS
7c3417bbf525c03163d54d151a277a981d5d61b6vboxsync/* Guest - protected mode */
8b984478b755f4d3091b977d9beac9fb7434279fvboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_PROT_STR(name)
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_PROT_STR(name)
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_PAE_PROT(name)
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_PAE_PROT_STR(name)
51d4024e2984de499ecd878341898f71f55cf9e0vboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_PAE_PROT_STR(name)
8b984478b755f4d3091b977d9beac9fb7434279fvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
e9a217d585085a6a6d129d27ca0d96a1b8e6d0eevboxsync#define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_PAE_PDPT_PHYS
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* 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)
f351fab06d1e1507b72f5c574df71193061fd393vboxsync#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)
f351fab06d1e1507b72f5c574df71193061fd393vboxsync#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
f351fab06d1e1507b72f5c574df71193061fd393vboxsync#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync * 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)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - AMD64 mode */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# define PGM_GST_NAME(name) PGM_GST_NAME_AMD64(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_AMD64_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_AMD64_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# define PGM_BTH_NAME(name) PGM_BTH_NAME_AMD64_AMD64(name)
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync# define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_AMD64_AMD64_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_AMD64_AMD64_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync# define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PAE_PT
5ace91141404400247438502a84a418fba00c8cfvboxsync# define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync# define BTH_PGMPOOLKIND_ROOT PGMPOOLKIND_64BIT_PML4
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_64_BITS_GUESTS */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Shadow - Nested paging mode
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync#define PGM_SHW_NAME(name) PGM_SHW_NAME_NESTED(name)
78a205e3fc6719d59e8c561b3d287d3a4f879852vboxsync#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)
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync/* Guest - real mode */
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_REAL_STR(name)
9e4166cf5ed4940f506bc718ea6c89bf7ed252c8vboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_REAL_STR(name)
0975ae0a0fb615c945150c48e4a73187c1f4f84dvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_NESTED_REAL(name)
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_NESTED_REAL_STR(name)
d07ea3c3faead54c0de83ab93f2b03dedfb819e2vboxsync#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 */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#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_NESTED_PROT(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#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)
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
247b55faa8d054157f2481e68caca36f4dc9542cvboxsync/* 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_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
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - PAE mode */
f351fab06d1e1507b72f5c574df71193061fd393vboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_PAE_STR(name)
3cbb4f9a6a320e58ed398ef7aaa004cc8727abc5vboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_PAE_STR(name)
f351fab06d1e1507b72f5c574df71193061fd393vboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_NESTED_PAE(name)
f351fab06d1e1507b72f5c574df71193061fd393vboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_NESTED_PAE_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_NESTED_PAE_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PAE_PT
3e6d3b0af632bdcd931b5149915c7b8be1a732cdvboxsync#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)
314f49cf51ddc0bbe5bc3551a02797b6636cf988vboxsync# 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)
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync# define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PAE_PT
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync# define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync#endif /* VBOX_WITH_64_BITS_GUESTS */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Shadow - EPT
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_SHW_NAME_RC_STR(name) PGM_SHW_NAME_RC_EPT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#define PGM_SHW_NAME_R0_STR(name) PGM_SHW_NAME_R0_EPT_STR(name)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/* Guest - real mode */
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsync#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)
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_REAL(name)
5ace91141404400247438502a84a418fba00c8cfvboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_EPT_REAL_STR(name)
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_EPT_REAL_STR(name)
42c1972c22e09797b4b24afbd0ec114ed076c37cvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
614cbe11a7e5588dc8d369e223174b1441a09359vboxsync/* Guest - protected mode */
614cbe11a7e5588dc8d369e223174b1441a09359vboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_PROT_STR(name)
ba919327d39360a78c5954ba29251e5e695e08b0vboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_PROT_STR(name)
614cbe11a7e5588dc8d369e223174b1441a09359vboxsync#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)
614cbe11a7e5588dc8d369e223174b1441a09359vboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PHYS
b5b12033c1f7eaf82b038f06e2b9e464b9ddd8d2vboxsync/* Guest - 32-bit mode */
d4b98dbce4cf7b3694b62d62a47553d399718dccvboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_32BIT_STR(name)
d4b98dbce4cf7b3694b62d62a47553d399718dccvboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_32BIT_STR(name)
d4b98dbce4cf7b3694b62d62a47553d399718dccvboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_32BIT(name)
b6d0062d24490dd07b4a424e5809b3b2bc910c5avboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_EPT_32BIT_STR(name)
21d4a56532f8029ae299f552811a0b86c1909416vboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_EPT_32BIT_STR(name)
b6d0062d24490dd07b4a424e5809b3b2bc910c5avboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_32BIT_PT
b6d0062d24490dd07b4a424e5809b3b2bc910c5avboxsync#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_32BIT_4MB
b978e5849454446957177fd47ee98609ab0457a6vboxsync/* Guest - PAE mode */
5ace91141404400247438502a84a418fba00c8cfvboxsync#define PGM_GST_NAME_RC_STR(name) PGM_GST_NAME_RC_PAE_STR(name)
5a12b9772d9cf396a0ba7f54db399817ba7a65bavboxsync#define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_PAE_STR(name)
b978e5849454446957177fd47ee98609ab0457a6vboxsync#define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_PAE(name)
b978e5849454446957177fd47ee98609ab0457a6vboxsync#define PGM_BTH_NAME_RC_STR(name) PGM_BTH_NAME_RC_EPT_PAE_STR(name)
b978e5849454446957177fd47ee98609ab0457a6vboxsync#define PGM_BTH_NAME_R0_STR(name) PGM_BTH_NAME_R0_EPT_PAE_STR(name)
5ace91141404400247438502a84a418fba00c8cfvboxsync#define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PAE_PT
5ace91141404400247438502a84a418fba00c8cfvboxsync#define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
5ace91141404400247438502a84a418fba00c8cfvboxsync/* Guest - AMD64 mode */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync# 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)
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync# define PGM_GST_NAME_R0_STR(name) PGM_GST_NAME_R0_AMD64_STR(name)
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync# define PGM_BTH_NAME(name) PGM_BTH_NAME_EPT_AMD64(name)
5ace91141404400247438502a84a418fba00c8cfvboxsync# 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)
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync# define BTH_PGMPOOLKIND_PT_FOR_PT PGMPOOLKIND_PAE_PT_FOR_PAE_PT
d94da006d266643454eaeeb7e54c7c4a06bff515vboxsync# define BTH_PGMPOOLKIND_PT_FOR_BIG PGMPOOLKIND_PAE_PT_FOR_PAE_2MB
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#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));
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync * Init the structure.
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync /* Init the per-CPU part. */
1fb9c510656583ba12872e082125263a58d9bc6bvboxsync for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pPGM->offVM = (uintptr_t)&pVCpu->pgm.s - (uintptr_t)pVM;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pPGM->offPGM = (uintptr_t)&pVCpu->pgm.s - (uintptr_t)&pVM->pgm.s;
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync 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;
09e2f92b8f54aa362088e216007b53ecdb42e283vboxsync rc = CFGMR3QueryBoolDef(CFGMR3GetRoot(pVM), "RamPreAlloc", &pVM->pgm.s.fRamPreAlloc,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = CFGMR3QueryU32Def(pCfgPGM, "MaxRing3Chunks", &pVM->pgm.s.ChunkR3Map.cMax, _1G / GMM_CHUNK_SIZE);
b978e5849454446957177fd47ee98609ab0457a6vboxsync rc = CFGMR3QueryU32Def(pCfgPGM, "MaxRing3Chunks", &pVM->pgm.s.ChunkR3Map.cMax, UINT32_MAX);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync for (uint32_t i = 0; i < RT_ELEMENTS(pVM->pgm.s.ChunkR3Map.Tlb.aEntries); i++)
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync pVM->pgm.s.ChunkR3Map.Tlb.aEntries[i].idChunk = NIL_GMM_CHUNKID;
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * Get the configured RAM size - to estimate saved state size.
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync 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");
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync * For the time being we sport a full set of handy pages in addition to the base
74735ec6edd6640eebac8885fbb2dadc86b89cf5vboxsync * memory to simplify things.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync rc = MMR3ReserveHandyPages(pVM, RT_ELEMENTS(pVM->pgm.s.aHandyPages)); /** @todo this should be changed to PGM_HANDY_PAGES_MIN but this needs proper testing... */
7aeda6afe5424afa9a456c400e6e7d539a38c716vboxsync rc = MMHyperAlloc(pVM, sizeof(PGMTREES), 0, MM_TAG_PGM, (void **)&pVM->pgm.s.pTreesR3);
f3e9d2446012445807621d8dd95afb2c8cad2789vboxsync pVM->pgm.s.pTreesR0 = MMHyperR3ToR0(pVM, pVM->pgm.s.pTreesR3);
e17f587595bd5d3a7be56a892e3fd3a0ef83d268vboxsync pVM->pgm.s.pTreesRC = MMHyperR3ToRC(pVM, pVM->pgm.s.pTreesR3);
e17f587595bd5d3a7be56a892e3fd3a0ef83d268vboxsync * Allocate the zero page.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync rc = MMHyperAlloc(pVM, PAGE_SIZE, PAGE_SIZE, MM_TAG_PGM, &pVM->pgm.s.pvZeroPgR3);
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync pVM->pgm.s.pvZeroPgRC = MMHyperR3ToRC(pVM, pVM->pgm.s.pvZeroPgR3);
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync pVM->pgm.s.pvZeroPgR0 = MMHyperR3ToR0(pVM, pVM->pgm.s.pvZeroPgR3);
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync pVM->pgm.s.HCPhysZeroPg = MMR3HyperHCVirt2HCPhys(pVM, pVM->pgm.s.pvZeroPgR3);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync AssertRelease(pVM->pgm.s.HCPhysZeroPg != NIL_RTHCPHYS);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * Allocate the invalid MMIO page.
cb70d239cc25c714044be945b6f7ff4f3a8b7cdfvboxsync * (The invalid bits in HCPhysInvMmioPg are set later on init complete.)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = MMHyperAlloc(pVM, PAGE_SIZE, PAGE_SIZE, MM_TAG_PGM, &pVM->pgm.s.pvMmioPgR3);
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync ASMMemFill32(pVM->pgm.s.pvMmioPgR3, PAGE_SIZE, 0xfeedface);
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync pVM->pgm.s.HCPhysMmioPg = MMR3HyperHCVirt2HCPhys(pVM, pVM->pgm.s.pvMmioPgR3);
ac6ddb9d00c1da301dfa25b0961dbd58b5f2f6e8vboxsync AssertRelease(pVM->pgm.s.HCPhysMmioPg != NIL_RTHCPHYS);
e17f587595bd5d3a7be56a892e3fd3a0ef83d268vboxsync pVM->pgm.s.HCPhysInvMmioPg = pVM->pgm.s.HCPhysMmioPg;
4b808cd07fd33b8a3edd0588dc43615686deb0e3vboxsync * Init the paging.
b5b12033c1f7eaf82b038f06e2b9e464b9ddd8d2vboxsync * Init the page pool.
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync * Info & statistics
016bd61cdd14201a24f289559b0cc333d8c94748vboxsync "Shows the current paging mode. "
016bd61cdd14201a24f289559b0cc333d8c94748vboxsync "Recognizes 'all', 'guest', 'shadow' and 'host' as arguments, defaulting to 'all' if nothing's given.",
4584ef6026a823006bea5acbeb13dc4efe50da69vboxsync "Dumps all the entries in the top level paging table. No arguments.",
4584ef6026a823006bea5acbeb13dc4efe50da69vboxsync "Dumps all the physical address ranges. No arguments.",
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync "Dumps physical, virtual and hyper virtual handlers. "
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync "Pass 'phys', 'virt', 'hyper' as argument if only one kind is wanted."
69deddbc68802f1cf1c3a404a9f816b8accb3385vboxsync "Add 'nost' if the statistics are unwanted, use together with 'all' or explicit selection.",
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync "Dumps guest mappings.",
13b9db9ae2c12b6c4e00eda5c79772d57a0d29e1vboxsync * Debugger commands.
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync static bool s_fRegisteredCmds = false;
21d4a56532f8029ae299f552811a0b86c1909416vboxsync int rc2 = DBGCRegisterCommands(&g_aCmds[0], RT_ELEMENTS(g_aCmds));
13b9db9ae2c12b6c4e00eda5c79772d57a0d29e1vboxsync /* Almost no cleanup necessary, MM frees all memory. */
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync * Initializes the per-VCPU PGM.
13b9db9ae2c12b6c4e00eda5c79772d57a0d29e1vboxsync * @returns VBox status code.
13b9db9ae2c12b6c4e00eda5c79772d57a0d29e1vboxsync * @param pVM The VM to operate on.
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * Init paging.
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * Since we need to check what mode the host is operating in before we can choose
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * the right paging functions for the host we have to delay this until R0 has
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync * 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));
2cd06fc737773d015b5268b9e4dfba5997915957vboxsync pVM->pgm.s.HCPhysInterPaePML4 = MMPage2Phys(pVM, pVM->pgm.s.pInterPaePML4);
13b9db9ae2c12b6c4e00eda5c79772d57a0d29e1vboxsync AssertRelease(pVM->pgm.s.HCPhysInterPaePML4 != NIL_RTHCPHYS && !(pVM->pgm.s.HCPhysInterPaePML4 & PAGE_OFFSET_MASK) && pVM->pgm.s.HCPhysInterPaePML4 < 0xffffffff);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * Initialize the pages, setting up the PML4 and PDPT for repetitive 4GB action.
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.apInterPaePDs); i++)
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync pVM->pgm.s.pInterPaePDPT->a[i].u = X86_PDPE_P | PGM_PLXFLAGS_PERMANENT
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.pInterPaePDPT64->a); i++)
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync const unsigned iPD = i % RT_ELEMENTS(pVM->pgm.s.apInterPaePDs);
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync pVM->pgm.s.pInterPaePDPT64->a[i].u = X86_PDPE_P | X86_PDPE_RW | X86_PDPE_US | X86_PDPE_A | PGM_PLXFLAGS_PERMANENT
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync RTHCPHYS HCPhysInterPaePDPT64 = MMPage2Phys(pVM, pVM->pgm.s.pInterPaePDPT64);
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.pInterPaePML4->a); i++)
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync pVM->pgm.s.pInterPaePML4->a[i].u = X86_PML4E_P | X86_PML4E_RW | X86_PML4E_US | X86_PML4E_A | PGM_PLXFLAGS_PERMANENT
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync * Initialize paging workers and mode from current host mode
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync * and the guest running in real mode.
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync AssertMsgFailed(("Host mode %d (64-bit) is not supported by non-64bit builds\n", pVM->pgm.s.enmHostMode));
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync LogRel(("Host mode %d (64-bit) is not supported by non-64bit builds\n", pVM->pgm.s.enmHostMode));
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync 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"));
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync LogRel(("Debug: HCPhysInterPD=%RHp HCPhysInterPaePDPT=%RHp HCPhysInterPaePML4=%RHp\n",
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync pVM->pgm.s.HCPhysInterPD, pVM->pgm.s.HCPhysInterPaePDPT, pVM->pgm.s.HCPhysInterPaePML4));
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync LogRel(("Debug: apInterPTs={%RHp,%RHp} apInterPaePTs={%RHp,%RHp} apInterPaePDs={%RHp,%RHp,%RHp,%RHp} pInterPaePDPT64=%RHp\n",
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync MMPage2Phys(pVM, pVM->pgm.s.apInterPTs[0]), MMPage2Phys(pVM, pVM->pgm.s.apInterPTs[1]),
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync MMPage2Phys(pVM, pVM->pgm.s.apInterPaePTs[0]), MMPage2Phys(pVM, pVM->pgm.s.apInterPaePTs[1]),
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync 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->cReusedSharedPages, STAMTYPE_U32, "/PGM/Page/cReusedSharedPages", STAMUNIT_COUNT, "The number of reused 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->cBalloonedPages, STAMTYPE_U32, "/PGM/Page/cBalloonedPages", STAMUNIT_COUNT, "The number of ballooned 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 STAM_REL_REG(pVM, &pPGM->cMappedChunks, STAMTYPE_U32, "/PGM/ChunkR3Map/Mapped", STAMUNIT_COUNT, "Number of times we mapped a chunk.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->cUnmappedChunks, STAMTYPE_U32, "/PGM/ChunkR3Map/Unmapped", STAMUNIT_COUNT, "Number of times we unmapped a chunk.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->StatLargePageAlloc, STAMTYPE_COUNTER, "/PGM/LargePage/Alloc", STAMUNIT_OCCURENCES, "The number of large pages we've used.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->StatLargePageReused, STAMTYPE_COUNTER, "/PGM/LargePage/Reused", STAMUNIT_OCCURENCES, "The number of times we've reused a large page.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->StatLargePageRefused, STAMTYPE_COUNTER, "/PGM/LargePage/Refused", STAMUNIT_OCCURENCES, "The number of times we couldn't use a large page.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync STAM_REL_REG(pVM, &pPGM->StatLargePageRecheck, STAMTYPE_COUNTER, "/PGM/LargePage/Recheck", STAMUNIT_OCCURENCES, "The number of times we've rechecked a disabled large page.");
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.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Mmio2.cZeroPages, STAMTYPE_U32, "/PGM/LiveSave/Mmio2/cZeroPages", STAMUNIT_COUNT, "MMIO2: Ready zero pages.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Mmio2.cMonitoredPages,STAMTYPE_U32, "/PGM/LiveSave/Mmio2/cMonitoredPages",STAMUNIT_COUNT, "MMIO2: Write monitored pages.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync# define PGM_REG_COUNTER(a, b, c) \
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync rc = STAMR3RegisterF(pVM, a, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, c, b); \
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync# define PGM_REG_COUNTER_BYTES(a, b, c) \
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync rc = STAMR3RegisterF(pVM, a, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, c, b); \
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync# define PGM_REG_PROFILE(a, b, c) \
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync rc = STAMR3RegisterF(pVM, a, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, c, b); \
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPGM->StatAllocLargePage, "/PGM/LargePage/Prof/Alloc", "Time spent by the host OS for large page allocation.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPGM->StatClearLargePage, "/PGM/LargePage/Prof/Clear", "Time spent clearing the newly allocated large pages.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPGM->StatR3IsValidLargePage, "/PGM/LargePage/Prof/R3/IsValid", "pgmPhysIsValidLargePage profiling - R3.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPGM->StatRZIsValidLargePage, "/PGM/LargePage/Prof/RZ/IsValid", "pgmPhysIsValidLargePage profiling - RZ.");
3ecd8008b81f02a04220705ae0033142af363280vboxsync 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.");
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatR3PhysWriteBytes, "/PGM/R3/Phys/Write/Bytes", "The number of bytes written by PGMPhysWrite.");
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync PGM_REG_COUNTER(&pPGM->StatR3PhysSimpleRead, "/PGM/R3/Phys/Simple/Read", "The number of times PGMPhysSimpleReadGCPtr was called.");
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatR3PhysSimpleReadBytes, "/PGM/R3/Phys/Simple/Read/Bytes", "The number of bytes read by PGMPhysSimpleReadGCPtr.");
8ddd175fa7cb232e090f3b8934a411c167aadb27vboxsync PGM_REG_COUNTER(&pPGM->StatR3PhysSimpleWrite, "/PGM/R3/Phys/Simple/Write", "The number of times PGMPhysSimpleWriteGCPtr was called.");
8ddd175fa7cb232e090f3b8934a411c167aadb27vboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatR3PhysSimpleWriteBytes, "/PGM/R3/Phys/Simple/Write/Bytes", "The number of bytes written by PGMPhysSimpleWriteGCPtr.");
7aeda6afe5424afa9a456c400e6e7d539a38c716vboxsync PGM_REG_COUNTER(&pPGM->StatRZChunkR3MapTlbHits, "/PGM/ChunkR3Map/TlbHitsRZ", "TLB hits.");
4b02cd4133ae0d8e4732c57274a59358e418349cvboxsync PGM_REG_COUNTER(&pPGM->StatRZChunkR3MapTlbMisses, "/PGM/ChunkR3Map/TlbMissesRZ", "TLB misses.");
4b02cd4133ae0d8e4732c57274a59358e418349cvboxsync PGM_REG_PROFILE(&pPGM->StatChunkAging, "/PGM/ChunkR3Map/Map/Aging", "Chunk aging profiling.");
4b02cd4133ae0d8e4732c57274a59358e418349cvboxsync PGM_REG_PROFILE(&pPGM->StatChunkFindCandidate, "/PGM/ChunkR3Map/Map/Find", "Chunk unmap find profiling.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_PROFILE(&pPGM->StatChunkUnmap, "/PGM/ChunkR3Map/Map/Unmap", "Chunk unmap of address space profiling.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_PROFILE(&pPGM->StatChunkMap, "/PGM/ChunkR3Map/Map/Map", "Chunk map of address space profiling.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER(&pPGM->StatRZPageMapTlbHits, "/PGM/RZ/Page/MapTlbHits", "TLB hits.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER(&pPGM->StatRZPageMapTlbMisses, "/PGM/RZ/Page/MapTlbMisses", "TLB misses.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER(&pPGM->StatR3ChunkR3MapTlbHits, "/PGM/ChunkR3Map/TlbHitsR3", "TLB hits.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER(&pPGM->StatR3ChunkR3MapTlbMisses, "/PGM/ChunkR3Map/TlbMissesR3", "TLB misses.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER(&pPGM->StatR3PageMapTlbHits, "/PGM/R3/Page/MapTlbHits", "TLB hits.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER(&pPGM->StatR3PageMapTlbMisses, "/PGM/R3/Page/MapTlbMisses", "TLB misses.");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER(&pPGM->StatPageMapTlbFlushes, "/PGM/R3/Page/MapTlbFlushes", "TLB flushes (all contexts).");
1171e4fb031146163c9a5a66bd9cbf3f2a5acdb6vboxsync PGM_REG_COUNTER(&pPGM->StatPageMapTlbFlushEntry, "/PGM/R3/Page/MapTlbFlushEntry", "TLB entry flushes (all contexts).");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync 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.");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync 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.");
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync PGM_REG_COUNTER(&pPGM->StatRZPhysHandlerReset, "/PGM/RZ/PhysHandlerReset", "The number of times PGMHandlerPhysicalReset is called.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER(&pPGM->StatR3PhysHandlerReset, "/PGM/R3/PhysHandlerReset", "The number of times PGMHandlerPhysicalReset is called.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_PROFILE(&pPGM->StatRZVirtHandlerSearchByPhys, "/PGM/RZ/VirtHandlerSearchByPhys", "Profiling of pgmHandlerVirtualFindByPhysAddr.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_PROFILE(&pPGM->StatR3VirtHandlerSearchByPhys, "/PGM/R3/VirtHandlerSearchByPhys", "Profiling of pgmHandlerVirtualFindByPhysAddr.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER(&pPGM->StatRZPageReplaceShared, "/PGM/RZ/Page/ReplacedShared", "Times a shared page was replaced.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER(&pPGM->StatRZPageReplaceZero, "/PGM/RZ/Page/ReplacedZero", "Times the zero page was replaced.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync/// @todo PGM_REG_COUNTER(&pPGM->StatRZPageHandyAllocs, "/PGM/RZ/Page/HandyAllocs", "Number of times we've allocated more handy pages.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER(&pPGM->StatR3PageReplaceShared, "/PGM/R3/Page/ReplacedShared", "Times a shared page was replaced.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER(&pPGM->StatR3PageReplaceZero, "/PGM/R3/Page/ReplacedZero", "Times the zero page was replaced.");
4b02cd4133ae0d8e4732c57274a59358e418349cvboxsync/// @todo PGM_REG_COUNTER(&pPGM->StatR3PageHandyAllocs, "/PGM/R3/Page/HandyAllocs", "Number of times we've allocated more handy pages.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatRZPhysRead, "/PGM/RZ/Phys/Read", "The number of times PGMPhysRead was called.");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRZPhysReadBytes, "/PGM/RZ/Phys/Read/Bytes", "The number of bytes read by PGMPhysRead.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatRZPhysWrite, "/PGM/RZ/Phys/Write", "The number of times PGMPhysWrite was called.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRZPhysWriteBytes, "/PGM/RZ/Phys/Write/Bytes", "The number of bytes written by PGMPhysWrite.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatRZPhysSimpleRead, "/PGM/RZ/Phys/Simple/Read", "The number of times PGMPhysSimpleReadGCPtr was called.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRZPhysSimpleReadBytes, "/PGM/RZ/Phys/Simple/Read/Bytes", "The number of bytes read by PGMPhysSimpleReadGCPtr.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatRZPhysSimpleWrite, "/PGM/RZ/Phys/Simple/Write", "The number of times PGMPhysSimpleWriteGCPtr was called.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRZPhysSimpleWriteBytes, "/PGM/RZ/Phys/Simple/Write/Bytes", "The number of bytes written by PGMPhysSimpleWriteGCPtr.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync /* GC only: */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPGM->StatRCDynMapCacheHits, "/PGM/RC/DynMapCache/Hits" , "Number of dynamic page mapping cache hits.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPGM->StatRCDynMapCacheMisses, "/PGM/RC/DynMapCache/Misses" , "Number of dynamic page mapping cache misses.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync 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.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPGM->StatRCPhysRead, "/PGM/RC/Phys/Read", "The number of times PGMPhysRead was called.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRCPhysReadBytes, "/PGM/RC/Phys/Read/Bytes", "The number of bytes read by PGMPhysRead.");
9b726ba798aabd1a27863e6f5cfeef1393bd198dvboxsync PGM_REG_COUNTER(&pPGM->StatRCPhysWrite, "/PGM/RC/Phys/Write", "The number of times PGMPhysWrite was called.");
9b726ba798aabd1a27863e6f5cfeef1393bd198dvboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRCPhysWriteBytes, "/PGM/RC/Phys/Write/Bytes", "The number of bytes written by PGMPhysWrite.");
9b726ba798aabd1a27863e6f5cfeef1393bd198dvboxsync PGM_REG_COUNTER(&pPGM->StatRCPhysSimpleRead, "/PGM/RC/Phys/Simple/Read", "The number of times PGMPhysSimpleReadGCPtr was called.");
9b726ba798aabd1a27863e6f5cfeef1393bd198dvboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRCPhysSimpleReadBytes, "/PGM/RC/Phys/Simple/Read/Bytes", "The number of bytes read by PGMPhysSimpleReadGCPtr.");
9b726ba798aabd1a27863e6f5cfeef1393bd198dvboxsync PGM_REG_COUNTER(&pPGM->StatRCPhysSimpleWrite, "/PGM/RC/Phys/Simple/Write", "The number of times PGMPhysSimpleWriteGCPtr was called.");
9b726ba798aabd1a27863e6f5cfeef1393bd198dvboxsync PGM_REG_COUNTER_BYTES(&pPGM->StatRCPhysSimpleWriteBytes, "/PGM/RC/Phys/Simple/Write/Bytes", "The number of bytes written by PGMPhysSimpleWriteGCPtr.");
9b726ba798aabd1a27863e6f5cfeef1393bd198dvboxsync PGM_REG_COUNTER(&pPGM->StatTrackVirgin, "/PGM/Track/Virgin", "The number of first time shadowings");
d9e767721ee71a4803f0de1e24f983be4faa4922vboxsync 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.");
8ddd175fa7cb232e090f3b8934a411c167aadb27vboxsync PGM_REG_COUNTER(&pPGM->StatTrackAliasedMany, "/PGM/Track/AliasedMany", "The number of times we're tracking using cRef2.");
fbf5c218f8bc15f0d765fef4b81e745f4db71b7avboxsync PGM_REG_COUNTER(&pPGM->StatTrackAliasedLots, "/PGM/Track/AliasedLots", "The number of times we're hitting pages which has overflowed cRef2");
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync PGM_REG_COUNTER(&pPGM->StatTrackOverflows, "/PGM/Track/Overflows", "The number of times the extent list grows too long.");
8ddd175fa7cb232e090f3b8934a411c167aadb27vboxsync PGM_REG_COUNTER(&pPGM->StatTrackNoExtentsLeft, "/PGM/Track/NoExtentLeft", "The number of times the extent list was exhausted.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPGM->StatTrackDeref, "/PGM/Track/Deref", "Profiling of SyncPageWorkerTrackDeref (expensive).");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * Note! The layout below matches the member layout exactly!
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync * Common - stats
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync#define PGM_REG_COUNTER(a, b, c) \
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync rc = STAMR3RegisterF(pVM, a, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, c, b, idCpu); \
3ecd8008b81f02a04220705ae0033142af363280vboxsync#define PGM_REG_PROFILE(a, b, c) \
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync rc = STAMR3RegisterF(pVM, a, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, c, b, idCpu); \
e8f172f2032e21b4be9a8f3df20e8ef689c6a6favboxsync PGM_REG_COUNTER(&pPgmCpu->cGuestModeChanges, "/PGM/CPU%u/cGuestModeChanges", "Number of guest mode changes.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync# if 0 /* rarely useful; leave for debugging. */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync for (unsigned j = 0; j < RT_ELEMENTS(pPgmCpu->StatSyncPtPD); j++)
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync STAMR3RegisterF(pVM, &pPgmCpu->StatSyncPtPD[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync "The number of SyncPT per PD n.", "/PGM/CPU%u/PDSyncPT/%04X", i, j);
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync for (unsigned j = 0; j < RT_ELEMENTS(pPgmCpu->StatSyncPagePD); j++)
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync STAMR3RegisterF(pVM, &pPgmCpu->StatSyncPagePD[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync "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.");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync PGM_REG_PROFILE(&pPgmCpu->StatR0DynMapGCPageInl, "/PGM/CPU%u/R0/DynMapPageGCPageInl", "Calls to pgmR0DynMapGCPageInlined.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapGCPageInlHits, "/PGM/CPU%u/R0/DynMapPageGCPageInl/Hits", "Hash table lookup hits.");
2cd06fc737773d015b5268b9e4dfba5997915957vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapGCPageInlMisses, "/PGM/CPU%u/R0/DynMapPageGCPageInl/Misses", "Misses that falls back to code common with PGMDynMapHCPage.");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapGCPageInlRamHits, "/PGM/CPU%u/R0/DynMapPageGCPageInl/RamHits", "1st ram range hits.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapGCPageInlRamMisses, "/PGM/CPU%u/R0/DynMapPageGCPageInl/RamMisses", "1st ram range misses, takes slow path.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_PROFILE(&pPgmCpu->StatR0DynMapHCPageInl, "/PGM/CPU%u/R0/DynMapPageHCPageInl", "Calls to pgmR0DynMapHCPageInlined.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapHCPageInlHits, "/PGM/CPU%u/R0/DynMapPageHCPageInl/Hits", "Hash table lookup hits.");
6c7440ab575cca1aa4d97d96b2d898a0d20c8efcvboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapHCPageInlMisses, "/PGM/CPU%u/R0/DynMapPageHCPageInl/Misses", "Misses that falls back to code common with PGMDynMapHCPage.");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapPage, "/PGM/CPU%u/R0/DynMapPage", "Calls to pgmR0DynMapPage");
2cd06fc737773d015b5268b9e4dfba5997915957vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapSetOptimize, "/PGM/CPU%u/R0/DynMapPage/SetOptimize", "Calls to pgmDynMapOptimizeAutoSet.");
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapSetSearchFlushes, "/PGM/CPU%u/R0/DynMapPage/SetSearchFlushes","Set search restorting to subset flushes.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapSetSearchHits, "/PGM/CPU%u/R0/DynMapPage/SetSearchHits", "Set search hits.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapSetSearchMisses, "/PGM/CPU%u/R0/DynMapPage/SetSearchMisses", "Set search misses.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatR0DynMapHCPage, "/PGM/CPU%u/R0/DynMapPage/HCPage", "Calls to PGMDynMapHCPage (ring-0).");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync 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");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync 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.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapPageSlow, "/PGM/CPU%u/R0/DynMapPage/Slow", "Calls to pgmR0DynMapPageSlow - subtract this from pgmR0DynMapPage to get 1st level hits.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapPageSlowLoopHits, "/PGM/CPU%u/R0/DynMapPage/SlowLoopHits" , "Hits in the loop path.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapPageSlowLoopMisses, "/PGM/CPU%u/R0/DynMapPage/SlowLoopMisses", "Misses in the loop path. NonLoopMisses = Slow - SlowLoopHit - SlowLoopMisses");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync //PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapPageSlowLostHits, "/PGM/CPU%u/R0/DynMapPage/SlowLostHits", "Lost hits.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatR0DynMapSubsets, "/PGM/CPU%u/R0/Subsets", "Times PGMDynMapPushAutoSubset was called.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync 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");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[1], "/PGM/CPU%u/R0/SetSize010..19", "10-19% filled");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[2], "/PGM/CPU%u/R0/SetSize020..29", "20-29% filled");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[3], "/PGM/CPU%u/R0/SetSize030..39", "30-39% filled");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[4], "/PGM/CPU%u/R0/SetSize040..49", "40-49% filled");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[5], "/PGM/CPU%u/R0/SetSize050..59", "50-59% filled");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[6], "/PGM/CPU%u/R0/SetSize060..69", "60-69% filled");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[7], "/PGM/CPU%u/R0/SetSize070..79", "70-79% filled");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[8], "/PGM/CPU%u/R0/SetSize080..89", "80-89% filled");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[9], "/PGM/CPU%u/R0/SetSize090..99", "90-99% filled");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->aStatR0DynMapSetSize[10], "/PGM/CPU%u/R0/SetSize100", "100% filled");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync /* RZ only: */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0e, "/PGM/CPU%u/RZ/Trap0e", "Profiling of the PGMTrap0eHandler() body.");
2b5a4cf3d77ab62dcbd882115b6d497547b20d29vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTimeCheckPageFault, "/PGM/CPU%u/RZ/Trap0e/Time/CheckPageFault", "Profiling of checking for dirty/access emulation faults.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTimeSyncPT, "/PGM/CPU%u/RZ/Trap0e/Time/SyncPT", "Profiling of lazy page table syncing.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTimeMapping, "/PGM/CPU%u/RZ/Trap0e/Time/Mapping", "Profiling of checking virtual mappings.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTimeOutOfSync, "/PGM/CPU%u/RZ/Trap0e/Time/OutOfSync", "Profiling of out of sync page handling.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTimeHandlers, "/PGM/CPU%u/RZ/Trap0e/Time/Handlers", "Profiling of checking handlers.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2CSAM, "/PGM/CPU%u/RZ/Trap0e/Time2/CSAM", "Profiling of the Trap0eHandler body when the cause is CSAM.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync 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.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2GuestTrap, "/PGM/CPU%u/RZ/Trap0e/Time2/GuestTrap", "Profiling of the Trap0eHandler body when the cause is a guest trap.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2HndPhys, "/PGM/CPU%u/RZ/Trap0e/Time2/HandlerPhysical", "Profiling of the Trap0eHandler body when the cause is a physical handler.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2HndVirt, "/PGM/CPU%u/RZ/Trap0e/Time2/HandlerVirtual", "Profiling of the Trap0eHandler body when the cause is a virtual handler.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync 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.");
90466ec66c4fa6a8cd62f01fbf141b51189d33cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZTrap0eTime2Misc, "/PGM/CPU%u/RZ/Trap0e/Time2/Misc", "Profiling of the Trap0eHandler body when the cause is not known.");
b9bd019c26def8e4d617c39121b62d7b8a826e96vboxsync 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.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync 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.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync 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.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync 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.");
a5c11842b92303b7b5d0086ee5011a969e321b50vboxsync 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.");
d184d98f6e75700295aaa08ff14d0478dd6cc94avboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eConflicts, "/PGM/CPU%u/RZ/Trap0e/Conflicts", "The number of times #PF was caused by an undetected conflict.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eHandlersMapping, "/PGM/CPU%u/RZ/Trap0e/Handlers/Mapping", "Number of traps due to access handlers in mappings.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync 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.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eHandlersVirtual, "/PGM/CPU%u/RZ/Trap0e/Handlers/Virtual", "Number of traps due to virtual access handlers.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync 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).");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eHandlersUnhandled, "/PGM/CPU%u/RZ/Trap0e/Handlers/Unhandled", "Number of traps due to access outside range of monitored page(s).");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eHandlersInvalid, "/PGM/CPU%u/RZ/Trap0e/Handlers/Invalid", "Number of traps due to access to invalid physical memory.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eUSNotPresentRead, "/PGM/CPU%u/RZ/Trap0e/Err/User/NPRead", "Number of user mode not present read page faults.");
d41220dff1068effe66bb6a11f444811ba58de40vboxsync 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.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eSVNotPresentWrite, "/PGM/CPU%u/RZ/Trap0e/Err/Supervisor/NPWrite", "Number of supervisor mode not present write page faults.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eSVWrite, "/PGM/CPU%u/RZ/Trap0e/Err/Supervisor/Write", "Number of supervisor mode write page faults.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eSVReserved, "/PGM/CPU%u/RZ/Trap0e/Err/Supervisor/Reserved", "Number of supervisor mode reserved bit page faults.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eSNXE, "/PGM/CPU%u/RZ/Trap0e/Err/Supervisor/NXE", "Number of supervisor mode NXE page faults.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eGuestPF, "/PGM/CPU%u/RZ/Trap0e/GuestPF", "Number of real guest page faults.");
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eGuestPFUnh, "/PGM/CPU%u/RZ/Trap0e/GuestPF/Unhandled", "Number of real guest page faults from the 'unhandled' case.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eGuestPFMapping, "/PGM/CPU%u/RZ/Trap0e/GuestPF/InMapping", "Number of real guest page faults in a mapping.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZTrap0eWPEmulInRZ, "/PGM/CPU%u/RZ/Trap0e/WP/InRZ", "Number of guest page faults due to X86_CR0_WP emulation.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync 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).");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync#if 0 /* rarely useful; leave for debugging. */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync for (unsigned j = 0; j < RT_ELEMENTS(pPgmCpu->StatRZTrap0ePD); j++)
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync STAMR3RegisterF(pVM, &pPgmCpu->StatRZTrap0ePD[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync "The number of traps in page directory n.", "/PGM/CPU%u/RZ/Trap0e/PD/%04X", i, j);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZGuestCR3WriteHandled, "/PGM/CPU%u/RZ/CR3WriteHandled", "The number of times the Guest CR3 change was successfully handled.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZGuestCR3WriteUnhandled, "/PGM/CPU%u/RZ/CR3WriteUnhandled", "The number of times the Guest CR3 change was passed back to the recompiler.");
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZGuestCR3WriteConflict, "/PGM/CPU%u/RZ/CR3WriteConflict", "The number of times the Guest CR3 monitoring detected a conflict.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZGuestROMWriteHandled, "/PGM/CPU%u/RZ/ROMWriteHandled", "The number of times the Guest ROM change was successfully handled.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZGuestROMWriteUnhandled, "/PGM/CPU%u/RZ/ROMWriteUnhandled", "The number of times the Guest ROM change was passed back to the recompiler.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync /* HC only: */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync /* RZ & R3: */
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZSyncCR3, "/PGM/CPU%u/RZ/SyncCR3", "Profiling of the PGMSyncCR3() body.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync PGM_REG_PROFILE(&pPgmCpu->StatRZSyncCR3Handlers, "/PGM/CPU%u/RZ/SyncCR3/Handlers", "Profiling of the PGMSyncCR3() update handler section.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync 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.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync 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.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZSyncPTFailed, "/PGM/CPU%u/RZ/SyncPT/Failed", "The number of times pfnSyncPT() failed.");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync 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");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZSyncPagePDOutOfSync, "/PGM/CPU%u/RZ/SyncPagePDOutOfSync", "The number of time we've encountered an out-of-sync PD in SyncPage.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZAccessedPage, "/PGM/CPU%u/RZ/AccessedPage", "The number of pages marked not present for accessed bit emulation.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync 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.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZDirtyPageBig, "/PGM/CPU%u/RZ/DirtyPage/MarkBig", "The number of 4MB pages marked read-only for dirty bit tracking.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZDirtyPageSkipped, "/PGM/CPU%u/RZ/DirtyPage/Skipped", "The number of pages already dirty or readonly.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync 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.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZDirtyTrackRealPF, "/PGM/CPU%u/RZ/DirtyPage/RealPF", "The number of real pages faults during dirty bit tracking.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync 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.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync 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.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZInvalidatePage4MBPagesSkip, "/PGM/CPU%u/RZ/InvalidatePage/4MBPagesSkip","The number of times PGMInvalidatePage() skipped a 4MB page.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync 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).");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZInvalidatePagePDNAs, "/PGM/CPU%u/RZ/InvalidatePage/PDNAs", "The number of times PGMInvalidatePage() was called for a not accessed page directory.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZInvalidatePagePDNPs, "/PGM/CPU%u/RZ/InvalidatePage/PDNPs", "The number of times PGMInvalidatePage() was called for a not present page directory.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync 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.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync 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.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZPageOutOfSyncBallloon, "/PGM/CPU%u/RZ/OutOfSync/Balloon", "The number of times a ballooned page was accessed (read).");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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)");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatRZFlushTLBNewCR3Global, "/PGM/CPU%u/RZ/FlushTLB/NewCR3Global", "The number of times PGMFlushTLB was called with a new CR3, global. (switch)");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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)");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_PROFILE(&pPgmCpu->StatR3SyncCR3, "/PGM/CPU%u/R3/SyncCR3", "Profiling of the PGMSyncCR3() body.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_PROFILE(&pPgmCpu->StatR3SyncCR3Handlers, "/PGM/CPU%u/R3/SyncCR3/Handlers", "Profiling of the PGMSyncCR3() update handler section.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncCR3Global, "/PGM/CPU%u/R3/SyncCR3/Global", "The number of global CR3 syncs.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncCR3NotGlobal, "/PGM/CPU%u/R3/SyncCR3/NotGlobal", "The number of non-global CR3 syncs.");
a5c11842b92303b7b5d0086ee5011a969e321b50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncCR3DstCacheHit, "/PGM/CPU%u/R3/SyncCR3/DstChacheHit", "The number of times we got some kind of a cache hit.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncPTFailed, "/PGM/CPU%u/R3/SyncPT/Failed", "The number of times pfnSyncPT() failed.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncPT4K, "/PGM/CPU%u/R3/SyncPT/4K", "Nr of 4K PT syncs");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3SyncPT4M, "/PGM/CPU%u/R3/SyncPT/4M", "Nr of 4M PT syncs");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync 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.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync 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.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync 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).");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3InvalidatePagePDNAs, "/PGM/CPU%u/R3/InvalidatePage/PDNAs", "The number of times PGMInvalidatePage() was called for a not accessed page directory.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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.");
ef481e64bafc49f1232767ce12c3fa69a5d5fe50vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3PageOutOfSyncBallloon, "/PGM/CPU%u/R3/OutOfSync/Balloon", "The number of times a ballooned page was accessed (read).");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync PGM_REG_PROFILE(&pPgmCpu->StatR3Prefetch, "/PGM/CPU%u/R3/Prefetch", "PGMPrefetchPage profiling.");
dea1368099e5337861dd52906d4c683c447a33c4vboxsync 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)");
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync 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)");
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync PGM_REG_COUNTER(&pPgmCpu->StatR3FlushTLBSameCR3Global, "/PGM/CPU%u/R3/FlushTLB/SameCR3Global", "The number of times PGMFlushTLB was called with the same CR3, global. (flush)");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PGM_REG_PROFILE(&pPgmCpu->StatR3GstModifyPage, "/PGM/CPU%u/R3/GstModifyPage", "Profiling of the PGMGstModifyPage() body.");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* VBOX_WITH_STATISTICS */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Init the PGM bits that rely on VMMR0 and MM to be fully initialized.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The dynamic mapping area will also be allocated and initialized at this
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * time. We could allocate it during PGMR3Init of course, but the mapping
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * wouldn't be allocated at that time preventing us from setting up the
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * page table entries with the dummy page.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 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))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync 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.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Reserve space for the dynamic mappings.
7e960d3a0a8a3a84d7aba2cca45d72b1c31cc97bvboxsync * Initialize the dynamic mapping pages with dummy pages to simply the cache.
b45d66c0e496e2fd861479202f3d43aad592bd14vboxsync /* 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;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVM->pgm.s.paDynPageMap32BitPTEsGC = pMapping->aPTs[iPT].pPTRC + iPG * sizeof(pMapping->aPTs[0].pPTR3->a[0]);
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync pVM->pgm.s.paDynPageMapPaePTEsGC = pMapping->aPTs[iPT].paPaePTsRC + iPG * sizeof(pMapping->aPTs[0].paPaePTsR3->a[0]);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* init cache */
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.aHCPhysDynPageMapCache); i++)
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync pVM->pgm.s.aHCPhysDynPageMapCache[i] = HCPhysDummy;
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync for (unsigned i = 0; i < MM_HYPER_DYNAMIC_SIZE; i += PAGE_SIZE)
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync rc = PGMMap(pVM, pVM->pgm.s.pbDynPageMapBaseGC + i, HCPhysDummy, PAGE_SIZE, 0);
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync * Determin the max physical address width (MAXPHYADDR) and apply it to
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync * all the mask members and stuff.
8b03ab0bcd5c238021bc8a43d887dd9d0870c0f5vboxsync cMaxPhysAddrWidth = ASMCpuId_EAX(0x80000008) & 0xff;
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync LogRel(("PGM: The CPU physical address width is %u bits\n", cMaxPhysAddrWidth));
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync pVM->pgm.s.fLessThan52PhysicalAddressBits = cMaxPhysAddrWidth < 52;
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync for (uint32_t iBit = cMaxPhysAddrWidth; iBit < 52; iBit++)
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync LogRel(("PGM: ASSUMING CPU physical address width of 48 bits (uMaxExtLeaf=%#x)\n", uMaxExtLeaf));
1ce20e84ae29a712029d1e213740388d7e158d5cvboxsync pVM->pgm.s.HCPhysInvMmioPg |= UINT64_C(0x000f0000000000);
c995102a21cae5b5ffeedadbfaddcc105809e196vboxsync for (uint32_t iBit = cMaxPhysAddrWidth; iBit < 64; iBit++)
3b5afcead60894f1a362df77eaeff7b7cdaee7a9vboxsync * Initialize the invalid paging entry masks, assuming NX is disabled.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint64_t fMbzPageFrameMask = pVM->pgm.s.GCPhysInvAddrMask & UINT64_C(0x000ffffffffff000);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo The manuals are not entirely clear whether the physical
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * address width is relevant. See table 5-9 in the intel
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * manual vs the PDE4M descriptions. Write testcase (NP). */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.fGst32BitMbzBigPdeMask = (uint32_t)(fMbzPageFrameMask >> (32 - 13)) | X86_PDE4M_MBZ_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.fGstPaeMbzPteMask = fMbzPageFrameMask | X86_PTE_PAE_MBZ_MASK_NO_NX;
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync pVCpu->pgm.s.fGstPaeMbzPdeMask = fMbzPageFrameMask | X86_PDE_PAE_MBZ_MASK_NO_NX;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.fGstPaeMbzBigPdeMask = fMbzPageFrameMask | X86_PDE2M_PAE_MBZ_MASK_NO_NX;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.fGstPaeMbzPdpeMask = fMbzPageFrameMask | X86_PDPE_PAE_MBZ_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.fGstAmd64MbzPteMask = fMbzPageFrameMask | X86_PTE_LM_MBZ_MASK_NO_NX;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.fGstAmd64MbzPdeMask = fMbzPageFrameMask | X86_PDE_LM_MBZ_MASK_NX;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.fGstAmd64MbzBigPdeMask = fMbzPageFrameMask | X86_PDE2M_LM_MBZ_MASK_NX;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.fGstAmd64MbzPdpeMask = fMbzPageFrameMask | X86_PDPE_LM_MBZ_MASK_NO_NX;
e85d76a7e5a047db3cdc8576ff5f412c7b73bbabvboxsync pVCpu->pgm.s.fGstAmd64MbzBigPdpeMask = fMbzPageFrameMask | X86_PDPE1G_LM_MBZ_MASK_NO_NX;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.fGstAmd64MbzPml4eMask = fMbzPageFrameMask | X86_PML4E_MBZ_MASK_NO_NX;
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync * Note that AMD uses all the 8 reserved bits for the address (so 40 bits in total);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * Intel only goes up to 36 bits, so we stick to 36 as well.
e85d76a7e5a047db3cdc8576ff5f412c7b73bbabvboxsync * Update: More recent intel manuals specifies 40 bits just like AMD.
e85d76a7e5a047db3cdc8576ff5f412c7b73bbabvboxsync CPUMGetGuestCpuId(VMMGetCpu(pVM), 1, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVM->pgm.s.GCPhys4MBPSEMask = RT_BIT_64(RT_MAX(36, cMaxPhysAddrWidth)) - 1;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Allocate memory if we're supposed to do that.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync LogRel(("PGMR3InitFinalize: 4 MB PSE mask %RGp\n", pVM->pgm.s.GCPhys4MBPSEMask));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Applies relocations to data and code managed by this component.
8f7bc6ad2b7bbcb4b3b96248cd2478e45f2e3b88vboxsync * This function will be called at init and whenever the VMM need to relocate it
5db1d52ffbcaa46c3d944c6c2d9c552306817d9avboxsync * self inside the GC.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param offDelta Relocation delta relative to old location.
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsyncVMMR3DECL(void) PGMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync LogFlow(("PGMR3Relocate %RGv to %RGv\n", pVM->pgm.s.GCPtrCR3Mapping, pVM->pgm.s.GCPtrCR3Mapping + offDelta));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Paging stuff.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pgmR3ModeDataInit(pVM, true /* resolve GC/R0 symbols */);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Shadow, guest and both mode switch & relocation for each VCPU. */
5db1d52ffbcaa46c3d944c6c2d9c552306817d9avboxsync pgmR3ModeDataSwitch(pVM, pVCpu, pVCpu->pgm.s.enmShadowMode, pVCpu->pgm.s.enmGuestMode);
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync pVM->pgm.s.pTreesRC = MMHyperR3ToRC(pVM, pVM->pgm.s.pTreesR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Ram ranges.
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync /* Update the pSelfRC pointers and relink them. */
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync 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)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!(pCur->RamRange.fFlags & PGM_RAM_RANGE_FLAGS_FLOATING))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCur->RamRange.pSelfRC = MMHyperCCToRC(pVM, &pCur->RamRange);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Update the two page directories with all page table mappings.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * (One or more of them have changed, that's why we're here.)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVM->pgm.s.pMappingsRC = MMHyperR3ToRC(pVM, pVM->pgm.s.pMappingsR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync 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)
abe73d9ccf5dd90fb1e3726792c56f2556a3d702vboxsync pCur->aPTs[i].pPTRC = MMHyperR3ToRC(pVM, pCur->aPTs[i].pPTR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCur->aPTs[i].paPaePTsRC = MMHyperR3ToRC(pVM, pCur->aPTs[i].paPaePTsR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Dynamic page mapping area.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The Zero page.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVM->pgm.s.pvZeroPgR0 = MMHyperR3ToR0(pVM, pVM->pgm.s.pvZeroPgR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertRelease(pVM->pgm.s.pvZeroPgR0 != NIL_RTR0PTR || !VMMIsHwVirtExtForced(pVM));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertRelease(pVM->pgm.s.pvZeroPgR0 != NIL_RTR0PTR);
74991d7531692858fd22acf371a7ee941567977cvboxsync * Physical and virtual handlers.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesR3->PhysHandlers, true, pgmR3RelocatePhysHandler, &offDelta);
57399ab65e2825c324fb9dcb4642d4ae2c232509vboxsync RTAvlroGCPtrDoWithAll(&pVM->pgm.s.pTreesR3->VirtHandlers, true, pgmR3RelocateVirtHandler, &offDelta);
3a21cbe769e7500039a2d17c794a911f7acb2dadvboxsync RTAvlroGCPtrDoWithAll(&pVM->pgm.s.pTreesR3->HyperVirtHandlers, true, pgmR3RelocateHyperVirtHandler, &offDelta);
3a21cbe769e7500039a2d17c794a911f7acb2dadvboxsync * The page pool.
6863baa4d9788245537c986d9caf02fb1893d2c6vboxsync * 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.
74991d7531692858fd22acf371a7ee941567977cvboxsyncstatic DECLCALLBACK(int) pgmR3RelocatePhysHandler(PAVLROGCPHYSNODECORE pNode, void *pvUser)
74991d7531692858fd22acf371a7ee941567977cvboxsync * 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.
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) pgmR3RelocateHyperVirtHandler(PAVLROGCPTRNODECORE pNode, void *pvUser)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(pHandler->enmType == PGMVIRTHANDLERTYPE_HYPERVISOR);
0174432b2b1a760b89840ba696f7ba51def65dddvboxsync * Resets a virtual CPU when unplugged.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVCpu The virtual CPU handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncVMMR3DECL(void) PGMR3ResetUnpluggedCpu(PVM pVM, PVMCPU pVCpu)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_REL_COUNTER_RESET(&pVCpu->pgm.s.cGuestModeChanges);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Re-init other members.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Clear the FFs PGM owns.
c33db29e7b41467a35675031f5f5233839909083vboxsync VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The VM is being reset.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * For the PGM component this means that any PD write monitors
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * needs to be removed.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @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!)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync STAM_REL_COUNTER_RESET(&pVCpu->pgm.s.cGuestModeChanges);
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * 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);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Reset (zero) RAM pages.
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * Reset (zero) shadow ROM pages.
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 /* Must free shared pages here. */
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * Terminates the per-VCPU PGM.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * Termination means cleaning up and freeing all resources,
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * the VM it self is at this point powered off or suspended.
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync * @returns VBox status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM to operate on.
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * Show paging mode.
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync * @param pVM VM Handle.
ec588a4ac8429a8b6c744544818b3ce3b2c75690vboxsync * @param pHlp The info helpers.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pszArgs "all" (default), "guest", "shadow" or "host".
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(void) pgmR3InfoMode(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
75fca099c974cbbd48f132af1378c60232614760vboxsync /* digest argument. */
a3db4ff1e0aa7f94c9176ef16264df572eec0aebvboxsync if (!pszArgs || !*pszArgs || strstr(pszArgs, "all"))
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo SMP support! */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync /* print info. */
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync pHlp->pfnPrintf(pHlp, "Guest paging mode: %s, changed %RU64 times, A20 %s\n",
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync PGMGetModeName(pVM->aCpus[0].pgm.s.enmGuestMode), pVM->aCpus[0].pgm.s.cGuestModeChanges.c,
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync pVM->aCpus[0].pgm.s.fA20Enabled ? "enabled" : "disabled");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync 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;
6b022885f2cb6a55167609edecd89570cd80001dvboxsync 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;
09d4e754a010196fe0d9d972b6ccc005ecb8b116vboxsync case SUPPAGINGMODE_AMD64_GLOBAL_NX: psz = "AMD64+G+NX"; break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHlp->pfnPrintf(pHlp, "Host paging mode: %s\n", psz);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 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)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "RAM ranges (pVM=%p)\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%.*s %.*s\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (PPGMRAMRANGE pCur = pVM->pgm.s.pRamRangesR3; pCur; pCur = pCur->pNextR3)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%RGp-%RGp %RHv %s\n",
3080f6c0871099df43a4e91b31894d9c2b1369a8vboxsync * Dump the page directory to the log.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * @param pVM VM Handle.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * @param pHlp The info helpers.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * @param pszArgs Arguments, ignored.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(void) pgmR3InfoCr3(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo SMP support!! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync/** @todo fix this! Convert the PGMR3DumpHierarchyHC functions to do guest stuff. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Big pages supported? */
9b45880674da6f82ca27cc28b0272de3dd3cc7dfvboxsync const bool fPSE = !!(CPUMGetGuestCR4(pVCpu) & X86_CR4_PSE);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync /* Global pages supported? */
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync const bool fPGE = !!(CPUMGetGuestCR4(pVCpu) & X86_CR4_PGE);
75fca099c974cbbd48f132af1378c60232614760vboxsync * Get page directory addresses.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(PGMPhysGCPhys2R3PtrAssert(pVM, (RTGCPHYS)(CPUMGetGuestCR3(pVCpu) & X86_CR3_PAGE_MASK), sizeof(*pPDSrc)) == pPDSrc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Iterate the page directory.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync 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);
a5c11842b92303b7b5d0086ee5011a969e321b50vboxsync "%04X - %RGp P=%d U=%d RW=%d [G=%d]\n",
09d4e754a010196fe0d9d972b6ccc005ecb8b116vboxsync PdeSrc.n.u1Present, PdeSrc.n.u1User, PdeSrc.n.u1Write, PdeSrc.b.u1Global && fPGE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Service a VMMCALLRING3_PGM_LOCK call.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = PDMR3CritSectEnterEx(&pVM->pgm.s.CritSect, true /* fHostCall */);
d6b5539478863f176bfffefc1ada2b9489cfa092vboxsync * Converts a PGMMODE value to a PGM_TYPE_* \#define.
d6b5539478863f176bfffefc1ada2b9489cfa092vboxsync * @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.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLINLINE(unsigned) pgmModeDataIndex(unsigned uShwType, unsigned uGstType)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(uShwType >= PGM_TYPE_32BIT && uShwType <= PGM_TYPE_MAX);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync Assert(uGstType >= PGM_TYPE_REAL && uGstType <= PGM_TYPE_AMD64);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return (uShwType - PGM_TYPE_32BIT) * (PGM_TYPE_AMD64 - PGM_TYPE_REAL + 1)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 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.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncDECLINLINE(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.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync 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.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVM->pgm.s.paModeData = (PPGMMODEDATA)MMR3HeapAllocZ(pVM, MM_TAG_PGM, sizeof(PGMMODEDATA) * pgmModeDataMaxIndex());
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReturn(pVM->pgm.s.paModeData, VERR_NO_MEMORY);
9a99bb9ca6c5bc8ef1977e01e13b05e5cc58319bvboxsync * Initialize the array entries.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_32BIT, PGM_TYPE_REAL)];
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync rc = PGM_SHW_NAME_32BIT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync rc = PGM_GST_NAME_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync rc = PGM_BTH_NAME_32BIT_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
fdc5224bd8d9a60af82da5809e3d6729c9bc69cbvboxsync 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);
9a99bb9ca6c5bc8ef1977e01e13b05e5cc58319bvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_PAE, PGM_TYPE_REAL)];
53317612c337db70bbfc72967860b3a00021e152vboxsync rc = PGM_SHW_NAME_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync rc = PGM_GST_NAME_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync rc = PGM_BTH_NAME_PAE_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_PAE, PGM_TYPE_PROT)];
d6b5539478863f176bfffefc1ada2b9489cfa092vboxsync rc = PGM_SHW_NAME_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync rc = PGM_GST_NAME_PROT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync rc = PGM_BTH_NAME_PAE_PROT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d6b5539478863f176bfffefc1ada2b9489cfa092vboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_PAE, PGM_TYPE_32BIT)];
23843d56d4bcd697cc8e0e6c9c01aec7baf6e72cvboxsync rc = PGM_SHW_NAME_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
52694110156cee1511e430c9ae800de121a20050vboxsync rc = PGM_GST_NAME_32BIT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync rc = PGM_BTH_NAME_PAE_32BIT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_PAE, PGM_TYPE_PAE)];
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync rc = PGM_SHW_NAME_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
26824086a3f6b36cd911058f1d9b4c0b944706fbvboxsync rc = PGM_GST_NAME_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
53317612c337db70bbfc72967860b3a00021e152vboxsync rc = PGM_BTH_NAME_PAE_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d6b5539478863f176bfffefc1ada2b9489cfa092vboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_AMD64, PGM_TYPE_AMD64)];
d6b5539478863f176bfffefc1ada2b9489cfa092vboxsync rc = PGM_SHW_NAME_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
9c2450ffd7e8a08cc596a2e4cc4d4e4dc9b382cfvboxsync rc = PGM_GST_NAME_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
9c2450ffd7e8a08cc596a2e4cc4d4e4dc9b382cfvboxsync rc = PGM_BTH_NAME_AMD64_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
9c2450ffd7e8a08cc596a2e4cc4d4e4dc9b382cfvboxsync /* The nested paging mode. */
9c2450ffd7e8a08cc596a2e4cc4d4e4dc9b382cfvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, PGM_TYPE_REAL)];
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync rc = PGM_GST_NAME_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
52694110156cee1511e430c9ae800de121a20050vboxsync rc = PGM_BTH_NAME_NESTED_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
016950bb1b289514e67d9e473538d22a50c0e408vboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, PGMMODE_PROTECTED)];
016950bb1b289514e67d9e473538d22a50c0e408vboxsync rc = PGM_GST_NAME_PROT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
016950bb1b289514e67d9e473538d22a50c0e408vboxsync rc = PGM_BTH_NAME_NESTED_PROT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
016950bb1b289514e67d9e473538d22a50c0e408vboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, PGM_TYPE_32BIT)];
016950bb1b289514e67d9e473538d22a50c0e408vboxsync rc = PGM_GST_NAME_32BIT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
5dda7f07dab8a954e6c4cf2378b15f921e60d9aavboxsync 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);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_NESTED_PAE(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync 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);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_NESTED_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* 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++)
1a25adaca81841abf5e6cdfed02eaff64941357dvboxsync 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);
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_PAE(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);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#endif /* HC_ARCH_BITS == 32 */
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync for (unsigned i = PGM_TYPE_REAL; i <= PGM_TYPE_AMD64; i++)
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync for (unsigned i = PGM_TYPE_REAL; i <= PGM_TYPE_PAE; i++)
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_NESTED, i)];
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync rc = PGM_SHW_NAME_AMD64(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync#endif /* HC_ARCH_BITS == 64 || RT_OS_DARWIN */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Extended paging (EPT) / Intel VT-x */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_EPT, PGM_TYPE_REAL)];
21d4a56532f8029ae299f552811a0b86c1909416vboxsync rc = PGM_SHW_NAME_EPT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
1a25adaca81841abf5e6cdfed02eaff64941357dvboxsync rc = PGM_GST_NAME_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_BTH_NAME_EPT_REAL(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pModeData = &pVM->pgm.s.paModeData[pgmModeDataIndex(PGM_TYPE_EPT, PGM_TYPE_PROT)];
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGM_SHW_NAME_EPT(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_EPT_PROT(InitData)( pVM, pModeData, fResolveGCAndR0); AssertRCReturn(rc, rc);
32f98f3d0fb00168315b4ece1f0808df4cd88248vboxsync 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));
afed5ab737f4aacfae3fe73776f40e989190a7cavboxsync /* shadow */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3ShwRelocate = pModeData->pfnR3ShwRelocate;
6b022885f2cb6a55167609edecd89570cd80001dvboxsync pVCpu->pgm.s.pfnR3ShwExit = pModeData->pfnR3ShwExit;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3ShwGetPage = pModeData->pfnR3ShwGetPage;
689e03ca2c98ca6feaab8d9de6e4687a98f14ccbvboxsync pVCpu->pgm.s.pfnR3ShwModifyPage = pModeData->pfnR3ShwModifyPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnRCShwGetPage = pModeData->pfnRCShwGetPage;
4b02cd4133ae0d8e4732c57274a59358e418349cvboxsync pVCpu->pgm.s.pfnRCShwModifyPage = pModeData->pfnRCShwModifyPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR0ShwGetPage = pModeData->pfnR0ShwGetPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR0ShwModifyPage = pModeData->pfnR0ShwModifyPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* guest */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3GstRelocate = pModeData->pfnR3GstRelocate;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3GstExit = pModeData->pfnR3GstExit;
689e03ca2c98ca6feaab8d9de6e4687a98f14ccbvboxsync pVCpu->pgm.s.pfnR3GstGetPage = pModeData->pfnR3GstGetPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3GstModifyPage = pModeData->pfnR3GstModifyPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3GstGetPDE = pModeData->pfnR3GstGetPDE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnRCGstGetPage = pModeData->pfnRCGstGetPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnRCGstModifyPage = pModeData->pfnRCGstModifyPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnRCGstGetPDE = pModeData->pfnRCGstGetPDE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR0GstGetPage = pModeData->pfnR0GstGetPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR0GstModifyPage = pModeData->pfnR0GstModifyPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR0GstGetPDE = pModeData->pfnR0GstGetPDE;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3BthRelocate = pModeData->pfnR3BthRelocate;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3BthInvalidatePage = pModeData->pfnR3BthInvalidatePage;
1a25adaca81841abf5e6cdfed02eaff64941357dvboxsync pVCpu->pgm.s.pfnR3BthSyncCR3 = pModeData->pfnR3BthSyncCR3;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnR3BthSyncPage = pModeData->pfnR3BthSyncPage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync 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;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnRCBthInvalidatePage = pModeData->pfnRCBthInvalidatePage;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pVCpu->pgm.s.pfnRCBthSyncCR3 = pModeData->pfnRCBthSyncCR3;
491e761460097c61edb725a77477cecb2774da45vboxsync pVCpu->pgm.s.pfnRCBthSyncPage = pModeData->pfnRCBthSyncPage;
491e761460097c61edb725a77477cecb2774da45vboxsync pVCpu->pgm.s.pfnRCBthPrefetchPage = pModeData->pfnRCBthPrefetchPage;
01cc79d6798a7ad8b8041ddb2b67fc8b37bf0b37vboxsync pVCpu->pgm.s.pfnRCBthVerifyAccessSyncPage = pModeData->pfnRCBthVerifyAccessSyncPage;
491e761460097c61edb725a77477cecb2774da45vboxsync 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;
afed5ab737f4aacfae3fe73776f40e989190a7cavboxsync * Calculates the shadow paging mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns The shadow paging mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param enmGuestMode The guest mode.
6b022885f2cb6a55167609edecd89570cd80001dvboxsync * @param enmHostMode The host mode.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param enmShadowMode The current shadow mode.
2f1b3d7474489e653b75edf9492132a0f56aab4dvboxsync * @param penmSwitcher Where to store the switcher to use.
ab1239d8445aa1fd4afddb7d0c8b90bbdc742010vboxsync * VMMSWITCHER_INVALID means no change.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic PGMMODE pgmR3CalcShadowMode(PVM pVM, PGMMODE enmGuestMode, SUPPAGINGMODE enmHostMode, PGMMODE enmShadowMode, VMMSWITCHER *penmSwitcher)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 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
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * and is supposed to determine which shadow paging and switcher to
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 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. */
75fca099c974cbbd48f132af1378c60232614760vboxsync default: AssertMsgFailed(("enmHostMode=%d\n", enmHostMode)); break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync default: AssertMsgFailed(("enmHostMode=%d\n", enmHostMode)); break;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReleaseMsgFailed(("enmGuestMode=%d\n", enmGuestMode));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Override the shadow mode is nested paging is active. */
b978e5849454446957177fd47ee98609ab0457a6vboxsync * Performs the actual mode change.
b978e5849454446957177fd47ee98609ab0457a6vboxsync * This is called by PGMChangeMode and pgmR3InitPaging().
b978e5849454446957177fd47ee98609ab0457a6vboxsync * @returns VBox status code. May suspend or power off the VM on error, but this
b978e5849454446957177fd47ee98609ab0457a6vboxsync * will trigger using FFs and not status codes.
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync * @param pVM VM handle.
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync * @param pVCpu The VMCPU to operate on.
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync * @param enmGuestMode The new guest mode. This is assumed to be different from
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync * the current mode.
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsyncVMMR3DECL(int) PGMR3ChangeMode(PVM pVM, PVMCPU pVCpu, PGMMODE enmGuestMode)
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync bool fIsOldGuestPagingMode64Bits = (pVCpu->pgm.s.enmGuestMode >= PGMMODE_AMD64);
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync bool fIsNewGuestPagingMode64Bits = (enmGuestMode >= PGMMODE_AMD64);
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync Log(("PGMR3ChangeMode: Guest mode: %s -> %s\n", PGMGetModeName(pVCpu->pgm.s.enmGuestMode), PGMGetModeName(enmGuestMode)));
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync STAM_REL_COUNTER_INC(&pVCpu->pgm.s.cGuestModeChanges);
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * Calc the shadow mode and switcher.
b978e5849454446957177fd47ee98609ab0457a6vboxsync PGMMODE enmShadowMode = pgmR3CalcShadowMode(pVM, enmGuestMode, pVM->pgm.s.enmHostMode, pVCpu->pgm.s.enmShadowMode, &enmSwitcher);
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync * Select new switcher.
020916e230faa4a37bace3a8480f54fac94ea173vboxsync AssertReleaseMsgFailed(("VMMR3SelectSwitcher(%d) -> %Rrc\n", enmSwitcher, rc));
020916e230faa4a37bace3a8480f54fac94ea173vboxsync * Exit old mode(s).
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync /* The nested shadow paging mode for AMD-V does change when running 64 bits guests on 32 bits hosts; typically PAE <-> AMD64 */
b66e14ead868d803cc49957974c34c4ea47346b4vboxsync const bool fForceShwEnterExit = ( fIsOldGuestPagingMode64Bits != fIsNewGuestPagingMode64Bits
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync const bool fForceShwEnterExit = false;
467e62e1aa999ec951e820d74498ef79dd1bedbdvboxsync /* shadow */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync LogFlow(("PGMR3ChangeMode: Shadow mode: %s -> %s\n", PGMGetModeName(pVCpu->pgm.s.enmShadowMode), PGMGetModeName(enmShadowMode)));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Exit failed for shadow mode %d: %Rrc\n", pVCpu->pgm.s.enmShadowMode, rc));
9c425bdea5f0991df62922b1584b805a86f2f898vboxsync LogFlow(("PGMR3ChangeMode: Shadow mode remains: %s\n", PGMGetModeName(pVCpu->pgm.s.enmShadowMode)));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* guest */
b978e5849454446957177fd47ee98609ab0457a6vboxsync AssertMsgFailed(("Exit failed for guest mode %d: %Rrc\n", pVCpu->pgm.s.enmGuestMode, rc));
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync * Load new paging mode data.
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync pgmR3ModeDataSwitch(pVM, pVCpu, enmShadowMode, enmGuestMode);
b978e5849454446957177fd47ee98609ab0457a6vboxsync * Enter new shadow mode (if changed).
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync rc = PGM_SHW_NAME_AMD64(Enter)(pVCpu, fIsNewGuestPagingMode64Bits);
020916e230faa4a37bace3a8480f54fac94ea173vboxsync rc = PGM_SHW_NAME_NESTED(Enter)(pVCpu, fIsNewGuestPagingMode64Bits);
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync rc = PGM_SHW_NAME_EPT(Enter)(pVCpu, fIsNewGuestPagingMode64Bits);
acba9722fdb2a8ee387985604a89e4507bda0789vboxsync AssertReleaseMsgFailed(("enmShadowMode=%d\n", enmShadowMode));
b66e14ead868d803cc49957974c34c4ea47346b4vboxsync AssertReleaseMsgFailed(("Entering enmShadowMode=%d failed: %Rrc\n", enmShadowMode, rc));
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync * Always flag the necessary updates
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * Enter the new guest and shadow+guest modes.
1718098fb08fdb7dafd85de1aaf51debc9e72828vboxsync rc = PGM_GST_NAME_REAL(Enter)(pVCpu, NIL_RTGCPHYS);
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync rc2 = PGM_BTH_NAME_32BIT_REAL(Enter)(pVCpu, NIL_RTGCPHYS);
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync rc2 = PGM_BTH_NAME_PAE_REAL(Enter)(pVCpu, NIL_RTGCPHYS);
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync rc2 = PGM_BTH_NAME_NESTED_REAL(Enter)(pVCpu, NIL_RTGCPHYS);
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync rc2 = PGM_BTH_NAME_EPT_REAL(Enter)(pVCpu, NIL_RTGCPHYS);
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync AssertMsgFailed(("Should use PAE shadow mode!\n"));
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync default: AssertFailed(); break;
020916e230faa4a37bace3a8480f54fac94ea173vboxsync rc = PGM_GST_NAME_PROT(Enter)(pVCpu, NIL_RTGCPHYS);
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync rc2 = PGM_BTH_NAME_32BIT_PROT(Enter)(pVCpu, NIL_RTGCPHYS);
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync rc2 = PGM_BTH_NAME_PAE_PROT(Enter)(pVCpu, NIL_RTGCPHYS);
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync rc2 = PGM_BTH_NAME_NESTED_PROT(Enter)(pVCpu, NIL_RTGCPHYS);
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync rc2 = PGM_BTH_NAME_EPT_PROT(Enter)(pVCpu, NIL_RTGCPHYS);
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync AssertMsgFailed(("Should use PAE shadow mode!\n"));
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync default: AssertFailed(); break;
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync GCPhysCR3 = CPUMGetGuestCR3(pVCpu) & X86_CR3_PAGE_MASK;
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync rc2 = PGM_BTH_NAME_32BIT_32BIT(Enter)(pVCpu, GCPhysCR3);
020916e230faa4a37bace3a8480f54fac94ea173vboxsync rc2 = PGM_BTH_NAME_PAE_32BIT(Enter)(pVCpu, GCPhysCR3);
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync rc2 = PGM_BTH_NAME_NESTED_32BIT(Enter)(pVCpu, GCPhysCR3);
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync rc2 = PGM_BTH_NAME_EPT_32BIT(Enter)(pVCpu, GCPhysCR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Should use PAE shadow mode!\n"));
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync default: AssertFailed(); break;
b978e5849454446957177fd47ee98609ab0457a6vboxsync CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return VMSetRuntimeError(pVM, VMSETRTERR_FLAGS_FATAL, "PAEmode",
020916e230faa4a37bace3a8480f54fac94ea173vboxsync 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)"));
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsync GCPhysCR3 = CPUMGetGuestCR3(pVCpu) & X86_CR3_PAE_PAGE_MASK;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc2 = PGM_BTH_NAME_PAE_PAE(Enter)(pVCpu, GCPhysCR3);
b978e5849454446957177fd47ee98609ab0457a6vboxsync rc2 = PGM_BTH_NAME_NESTED_PAE(Enter)(pVCpu, GCPhysCR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc2 = PGM_BTH_NAME_EPT_PAE(Enter)(pVCpu, GCPhysCR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertMsgFailed(("Should use PAE shadow mode!\n"));
223cf005b18af2c21352a70693ebaf0582f68ebcvboxsync default: AssertFailed(); break;
b978e5849454446957177fd47ee98609ab0457a6vboxsync GCPhysCR3 = CPUMGetGuestCR3(pVCpu) & UINT64_C(0xfffffffffffff000); /** @todo define this mask! */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc2 = PGM_BTH_NAME_AMD64_AMD64(Enter)(pVCpu, GCPhysCR3);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc2 = PGM_BTH_NAME_NESTED_AMD64(Enter)(pVCpu, GCPhysCR3);
b978e5849454446957177fd47ee98609ab0457a6vboxsync rc2 = PGM_BTH_NAME_EPT_AMD64(Enter)(pVCpu, GCPhysCR3);
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync AssertMsgFailed(("Should use AMD64 shadow mode!\n"));
b978e5849454446957177fd47ee98609ab0457a6vboxsync default: AssertFailed(); break;
b978e5849454446957177fd47ee98609ab0457a6vboxsync AssertReleaseMsgFailed(("enmGuestMode=%d\n", enmGuestMode));
b978e5849454446957177fd47ee98609ab0457a6vboxsync /* status codes. */
b978e5849454446957177fd47ee98609ab0457a6vboxsync if (RT_SUCCESS(rc)) /* no informational status codes. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* Notify HWACCM as well. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync HWACCMR3PagingModeChanged(pVM, pVCpu, pVCpu->pgm.s.enmShadowMode, pVCpu->pgm.s.enmGuestMode);
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * Called by pgmPoolFlushAllInt prior to flushing the pool.
11c599b71a8c202a506b8623af57432c3d415ddavboxsync * @returns VBox status code, fully asserted.
11c599b71a8c202a506b8623af57432c3d415ddavboxsync * @param pVM The VM handle.
11c599b71a8c202a506b8623af57432c3d415ddavboxsync * @param pVCpu The VMCPU to operate on.
965a56f05878cf7c9634998e98d0bed41ebf21dbvboxsyncint pgmR3ExitShadowModeBeforePoolFlush(PVM pVM, PVMCPU pVCpu)
11c599b71a8c202a506b8623af57432c3d415ddavboxsync /* Unmap the old CR3 value before flushing everything. */
11c599b71a8c202a506b8623af57432c3d415ddavboxsync /* Exit the current shadow paging mode as well; nested paging and EPT use a root CR3 which will get flushed here. */
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync * Called by pgmPoolFlushAllInt after flushing the pool.
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync * @returns VBox status code, fully asserted.
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync * @param pVM The VM handle.
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync * @param pVCpu The VMCPU to operate on.
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsyncint pgmR3ReEnterShadowModeAfterPoolFlush(PVM pVM, PVMCPU pVCpu)
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync int rc = PGMR3ChangeMode(pVM, pVCpu, PGMGetGuestMode(pVCpu));
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync Assert(VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync AssertRCSuccessReturn(rc, VERR_IPE_UNEXPECTED_INFO_STATUS);
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync AssertMsg( pVCpu->pgm.s.enmShadowMode >= PGMMODE_NESTED
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync || CPUMGetHyperCR3(pVCpu) == PGMGetHyperCR3(pVCpu),
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync ("%RHp != %RHp %s\n", (RTHCPHYS)CPUMGetHyperCR3(pVCpu), PGMGetHyperCR3(pVCpu), PGMGetModeName(pVCpu->pgm.s.enmShadowMode)));
b301c2ed80b2ae5201801c30b37618a158fcc14evboxsync * Dumps a PAE shadow page table.
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync * @returns VBox status code (VINF_SUCCESS).
b301c2ed80b2ae5201801c30b37618a158fcc14evboxsync * @param pVM The VM handle.
b301c2ed80b2ae5201801c30b37618a158fcc14evboxsync * @param pPT Pointer to the page table.
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsync * @param u64Address The virtual address of the page table starts.
b301c2ed80b2ae5201801c30b37618a158fcc14evboxsync * @param fLongMode Set if this a long mode table; clear if it's a legacy mode table.
b301c2ed80b2ae5201801c30b37618a158fcc14evboxsync * @param cMaxDepth The maxium depth.
b301c2ed80b2ae5201801c30b37618a158fcc14evboxsync * @param pHlp Pointer to the output functions.
fc4516250f652da12d477446bc5351bcf6c5aaebvboxsyncstatic int pgmR3DumpHierarchyHCPaePT(PVM pVM, PX86PTPAE pPT, uint64_t u64Address, bool fLongMode, unsigned cMaxDepth, PCDBGFINFOHLP pHlp)
11c599b71a8c202a506b8623af57432c3d415ddavboxsync ? "%016llx 3 | P %c %c %c %c %c %s %s %s %s 4K %c%c%c %016llx\n"
11c599b71a8c202a506b8623af57432c3d415ddavboxsync : "%08llx 2 | P %c %c %c %c %c %s %s %s %s 4K %c%c%c %016llx\n",
020916e230faa4a37bace3a8480f54fac94ea173vboxsync * Dumps a PAE shadow page directory table.
b978e5849454446957177fd47ee98609ab0457a6vboxsync * @returns VBox status code (VINF_SUCCESS).
11c599b71a8c202a506b8623af57432c3d415ddavboxsync * @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.
fbf5c218f8bc15f0d765fef4b81e745f4db71b7avboxsync * @param fLongMode Set if this a long mode table; clear if it's a legacy mode table.
9984bae4ef25be8afd95d184308adcfef6e2ec0dvboxsync * @param cMaxDepth The maxium depth.
11c599b71a8c202a506b8623af57432c3d415ddavboxsync * @param pHlp Pointer to the output functions.
11c599b71a8c202a506b8623af57432c3d415ddavboxsyncstatic int pgmR3DumpHierarchyHCPaePD(PVM pVM, RTHCPHYS HCPhys, uint64_t u64Address, uint32_t cr4, bool fLongMode, unsigned cMaxDepth, PCDBGFINFOHLP pHlp)
965a56f05878cf7c9634998e98d0bed41ebf21dbvboxsync PX86PDPAE pPD = (PX86PDPAE)MMPagePhys2Page(pVM, HCPhys);
bbbec97e47d726fe8f4ccf775c971846b3dde7eevboxsync pHlp->pfnPrintf(pHlp, "%0*llx error! Page directory at HCPhys=%RHp was not found in the page pool!\n",
11c599b71a8c202a506b8623af57432c3d415ddavboxsync const bool fBigPagesSupported = fLongMode || !!(cr4 & X86_CR4_PSE);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ? "%016llx 2 | P %c %c %c %c %c %s %s %s %s 4M %c%c%c %016llx\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync : "%08llx 1 | P %c %c %c %c %c %s %s %s %s 4M %c%c%c %016llx\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ? "%016llx 2 | P %c %c %c %c %c %s %s .. %s 4K %c%c%c %016llx\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync : "%08llx 1 | P %c %c %c %c %c %s %s .. %s 4K %c%c%c %016llx\n",
ea04f885ccd9a758072e975806b1275d9afaac06vboxsync /** @todo what about using the page pool for mapping PTs? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync uint64_t u64AddressPT = u64Address + ((uint64_t)i << X86_PD_PAE_SHIFT);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (PPGMMAPPING pMap = pVM->pgm.s.pMappingsR3; pMap; pMap = pMap->pNextR3)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync const int iSub = (int)((off >> X86_PD_PAE_SHIFT) & 1); /* MSC is a pain sometimes */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if ((iSub ? pMap->aPTs[iPDE].HCPhysPaePT1 : pMap->aPTs[iPDE].HCPhysPaePT0) != HCPhysPT)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHlp->pfnPrintf(pHlp, "%0*llx error! Mapping error! PT %d has HCPhysPT=%RHp not %RHp is in the PD.\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync iSub ? pMap->aPTs[iPDE].HCPhysPaePT1 : pMap->aPTs[iPDE].HCPhysPaePT0, HCPhysPT);
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync rc2 = pgmR3DumpHierarchyHCPaePT(pVM, pPT, u64AddressPT, fLongMode, cMaxDepth - 1, pHlp);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHlp->pfnPrintf(pHlp, "%0*llx error! Page table at HCPhys=%RHp was not found in the page pool!\n",
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * Dumps a PAE shadow page directory pointer table.
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync * @returns VBox status code (VINF_SUCCESS).
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * @param pVM The VM handle.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param HCPhys The physical address of the page directory pointer table.
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync * @param u64Address The virtual address of the page table starts.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @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.
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * @param cMaxDepth The maxium depth.
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync * @param pHlp Pointer to the output functions.
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsyncstatic int pgmR3DumpHierarchyHCPaePDPT(PVM pVM, RTHCPHYS HCPhys, uint64_t u64Address, uint32_t cr4, bool fLongMode, unsigned cMaxDepth, PCDBGFINFOHLP pHlp)
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync 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",
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync const unsigned c = fLongMode ? RT_ELEMENTS(pPDPT->a) : X86_PG_PAE_PDPE_ENTRIES;
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync for (unsigned i = 0; i < c; i++)
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync pHlp->pfnPrintf(pHlp, /*P R S A D G WT CD AT NX 4M a p ? */
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync "%016llx 1 | P %c %c %c %c %c %s %s %s %s .. %c%c%c %016llx\n",
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync pHlp->pfnPrintf(pHlp, /*P G WT CD AT NX 4M a p ? */
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync "%08x 0 | P %c %s %s %s %s .. %c%c%c %016llx\n",
55a158b986cee4c4ebe1a650e8727e1c6905e32evboxsync 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.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param HCPhys The physical address of the table.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cr4 The CR4, PSE is currently used.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cMaxDepth The maxium depth.
da936e0446fb2b56b813d5d938f1dfc6e4bf8b13vboxsync * @param pHlp Pointer to the output functions.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic int pgmR3DumpHierarchyHcPaePML4(PVM pVM, RTHCPHYS HCPhys, uint32_t cr4, unsigned cMaxDepth, PCDBGFINFOHLP pHlp)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PX86PML4 pPML4 = (PX86PML4)MMPagePhys2Page(pVM, HCPhys);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHlp->pfnPrintf(pHlp, "Page map level 4 at HCPhys=%RHp was not found in the page pool!\n", HCPhys);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (unsigned i = 0; i < RT_ELEMENTS(pPML4->a); i++)
1b7f3a92e42fb9cabf96cf31c20481da466edf76vboxsync uint64_t u64Address = ((uint64_t)i << X86_PML4_SHIFT) | (((uint64_t)i >> (X86_PML4_SHIFT - X86_PDPT_SHIFT - 1)) * 0xffff000000000000ULL);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync 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",
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync int rc2 = pgmR3DumpHierarchyHCPaePDPT(pVM, Pml4e.u & X86_PML4E_PG_MASK, u64Address, cr4, true, cMaxDepth - 1, pHlp);
da936e0446fb2b56b813d5d938f1dfc6e4bf8b13vboxsync * Dumps a 32-bit shadow page table.
5db1d52ffbcaa46c3d944c6c2d9c552306817d9avboxsync * @returns VBox status code (VINF_SUCCESS).
da936e0446fb2b56b813d5d938f1dfc6e4bf8b13vboxsync * @param pVM The VM handle.
585f64d6f624f9e683321dabeb21b0eb2e6aa473vboxsync * @param pPT Pointer to the page table.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param u32Address The virtual address this table starts at.
54fe68d807196dc565de24055996e634ee40ee92vboxsync * @param pHlp Pointer to the output functions.
da936e0446fb2b56b813d5d938f1dfc6e4bf8b13vboxsyncint pgmR3DumpHierarchyHC32BitPT(PVM pVM, PX86PT pPT, uint32_t u32Address, PCDBGFINFOHLP pHlp)
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync pHlp->pfnPrintf(pHlp, /*P R S A D G WT CD AT NX 4M a m d */
ec588a4ac8429a8b6c744544818b3ce3b2c75690vboxsync "%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.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * @returns VBox status code (VINF_SUCCESS).
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * @param pVM The VM handle.
00599f6d39cc25ca39845c2433cd75de7b9f6971vboxsync * @param cr3 The root of the hierarchy.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cr4 The CR4, PSE is currently used.
4b02cd4133ae0d8e4732c57274a59358e418349cvboxsync * @param cMaxDepth How deep into the hierarchy the dumper should go.
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync * @param pHlp Pointer to the output functions.
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsyncint pgmR3DumpHierarchyHC32BitPD(PVM pVM, uint32_t cr3, uint32_t cr4, unsigned cMaxDepth, PCDBGFINFOHLP pHlp)
e751d1e1e4ae424d4846a23da32f663d14960796vboxsync PX86PD pPD = (PX86PD)MMPagePhys2Page(pVM, cr3 & X86_CR3_PAGE_MASK);
b0065cd95da56e4208839eb0d3963472c688a8d4vboxsync pHlp->pfnPrintf(pHlp, "Page directory at %#x was not found in the page pool!\n", cr3 & X86_CR3_PAGE_MASK);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync pHlp->pfnPrintf(pHlp, /*P R S A D G WT CD AT NX 4M a m d */
4b02cd4133ae0d8e4732c57274a59358e418349cvboxsync "%08x 0 | P %c %c %c %c %c %s %s %s .. 4M %c%c%c %08x\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHlp->pfnPrintf(pHlp, /*P R S A D G WT CD AT NX 4M a m d */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%08x 0 | P %c %c %c %c %c %s %s .. .. 4K %c%c%c %08x\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo what about using the page pool for mapping PTs? */
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync 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);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pHlp->pfnPrintf(pHlp, "%08x error! Page table at %#x was not found in the page pool!\n", u32Address, HCPhys);
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.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param u32Address The virtual address this table starts at.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param PhysSearch Address to search for.
50df3da42ff6589b0ecc4f50f2288811bc370186vboxsyncint pgmR3DumpHierarchyGC32BitPT(PVM pVM, PX86PT pPT, uint32_t u32Address, RTGCPHYS PhysSearch)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%08x 1 | P %c %c %c %c %c %s %s %s .. 4K %c%c%c %08x\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo SMP support!! */
6b022885f2cb6a55167609edecd89570cd80001dvboxsync PGMShwGetPage(&pVM->aCpus[0], (RTGCPTR)(u32Address + (i << X86_PT_SHIFT)), &fPageShw, &pPhysHC);
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync 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.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param cr3 The root of the hierarchy.
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync * @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);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync int rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, cr3 & X86_CR3_PAGE_MASK, (const void **)&pPD, &LockCr3);
0138777a0eae9d74905d86f792f1f1c497dab65evboxsync Log(("Page directory at %#x was not found in the page pool!\n", cr3 & X86_CR3_PAGE_MASK));
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync "%-*s P - Present\n"
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync "%-*s | R/W - Read (0) / Write (1)\n"
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync "%-*s | | U/S - User (1) / Supervisor (0)\n"
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync "%-*s | | | A - Accessed\n"
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync "%-*s | | | | D - Dirty\n"
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync "%-*s | | | | | G - Global\n"
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync "%-*s | | | | | | WT - Write thru\n"
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync "%-*s | | | | | | | CD - Cache disable\n"
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync "%-*s | | | | | | | | AT - Attribute table (PAT)\n"
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync "%-*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"
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync "%-*s Level | | | | | | | | | | | | Page\n"
1986f56777969a25707ab214f8dd070804be666cvboxsync /* xxxx n **** P R S A D G WT CD AT NX 4M AVL xxxxxxxxxxxxx
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync - W U - - - -- -- -- -- -- 010 */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cch, "", cch, "", cch, "", cch, "", cch, "", cch, "", cch, "",
053eccf0693eaef856866aef1a8b7ee4abf11f1fvboxsync 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 */
fa88302d5e91b79aeae01c928f33437088a90153vboxsync "%08x 0 | P %c %c %c %c %c %s %s .. .. 4K %c%c%c %08x\n",
65ff326ac3915638f5c4e79c2c3e836aeeeb86devboxsync ////if (cMaxDepth >= 1)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /** @todo what about using the page pool for mapping PTs? */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys, (const void **)&pPT, &LockPT);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync rc2 = pgmR3DumpHierarchyGC32BitPT(pVM, pPT, u32Address, PhysSearch);
65ff326ac3915638f5c4e79c2c3e836aeeeb86devboxsync Log(("%08x error! Page table at %#x was not found in the page pool!\n", u32Address, GCPhys));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Dumps a page table hierarchy use only physical addresses and cr4/lm flags.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status code (VINF_SUCCESS).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pVM The VM handle.
65ff326ac3915638f5c4e79c2c3e836aeeeb86devboxsync * @param cr3 The root of the hierarchy.
1986f56777969a25707ab214f8dd070804be666cvboxsync * @param cr4 The cr4, only PAE and PSE is currently used.
65ff326ac3915638f5c4e79c2c3e836aeeeb86devboxsync * @param fLongMode Set if long mode, false if not long mode.
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync * @param cMaxDepth Number of levels to dump.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pHlp Pointer to the output functions.
65ff326ac3915638f5c4e79c2c3e836aeeeb86devboxsyncVMMR3DECL(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"
5007ad5d2bce84d88ee339a94e0aa7b91c699194vboxsync "%-*s | R/W - Read (0) / Write (1)\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | U/S - User (1) / Supervisor (0)\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | A - Accessed\n"
1986f56777969a25707ab214f8dd070804be666cvboxsync "%-*s | | | | D - Dirty\n"
d7f733dd34ab7755807d85016b7c2ab3d1a362d4vboxsync "%-*s | | | | | G - Global\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | | | WT - Write thru\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | | | | CD - Cache disable\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%-*s | | | | | | | | AT - Attribute table (PAT)\n"
020916e230faa4a37bace3a8480f54fac94ea173vboxsync "%-*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
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync - W U - - - -- -- -- -- -- 010 */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync cch, "", cch, "", cch, "", cch, "", cch, "", cch, "", cch, "",
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync cch, "", cch, "", cch, "", cch, "", cch, "", cch, "", cch, "Address");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pgmR3DumpHierarchyHcPaePML4(pVM, cr3 & X86_CR3_PAGE_MASK, cr4, cMaxDepth, pHlp);
65ff326ac3915638f5c4e79c2c3e836aeeeb86devboxsync 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.
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.
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync * @param cArgs Number of arguments in the array.
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsyncstatic DECLCALLBACK(int) pgmR3CmdRam(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate input.
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync 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");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync for (pRam = pVM->pgm.s.pRamRangesR3; pRam; pRam = pRam->pNextR3)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "%RGp - %RGp %p\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The '.pgmerror' and '.pgmerroroff' commands.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pCmd Pointer to the command descriptor (as registered).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pCmdHlp Pointer to command helper functions.
4668308b1dc311a789186f2fc7971394b6f26a92vboxsync * @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) pgmR3CmdError(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 AssertReturn(cArgs == 0 || (cArgs == 1 && paArgs[0].enmType == DBGCVAR_TYPE_STRING),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Hit bug in the parser.\n"));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Print the list of error injection locations with status.
bee80f3f77b15c166b7debd080a70e5231ba6751vboxsync pCmdHlp->pfnPrintf(pCmdHlp, NULL, "PGM error inject locations:\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCmdHlp->pfnPrintf(pCmdHlp, NULL, " handy - %RTbool\n", pVM->pgm.s.fErrInjHandyPages);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * String switch on where to inject the error.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync bool const fNewState = !strcmp(pCmd->pszCmd, "pgmerror");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ASMAtomicWriteBool(&pVM->pgm.s.fErrInjHandyPages, fNewState);
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: Invalid 'where' value: %s.\n", pszWhere);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * 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.
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync * @param cArgs Number of arguments in the array.
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsyncstatic DECLCALLBACK(int) pgmR3CmdSync(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync /** @todo SMP support */
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync * Validate input.
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Force page directory sync.
b1c3cdef473df2fbc621d5da81acc82dbfb8a11avboxsync int rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Forcing page directory sync.\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * The '.pgmassertcr3' command.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns VBox status.
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync * @param pCmd Pointer to the command descriptor (as registered).
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pCmdHlp Pointer to command helper functions.
a08545103bb86795ec6acde73aa6d217a51ce731vboxsync * @param pVM Pointer to the current VM (if any).
92e770dbf167ee799d35dd505ccce02be76b85fcvboxsync * @param paArgs Pointer to (readonly) array of arguments.
fa7355597d7eba5b4ca8a23056ebe1b8fb306fdbvboxsync * @param cArgs Number of arguments in the array.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic 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");
aaeb2e2f6ed5b164f1dec9a16a7adeb84f64cf31vboxsync int rc = pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Checking shadow CR3 page tables for consistency.\n");
53163a75972769c720ae0b51a007ce4de6408778vboxsync PGMAssertCR3(pVM, pVCpu, CPUMGetGuestCR3(pVCpu), CPUMGetGuestCR4(pVCpu));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync#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.
53163a75972769c720ae0b51a007ce4de6408778vboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
53163a75972769c720ae0b51a007ce4de6408778vboxsync * Force page directory sync.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ASMAtomicAndU32(&pVCpu->pgm.s.fSyncFlags, ~PGM_SYNC_ALWAYS);
6f516ad9911d9037a18778742caa955fe362f8ffvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Disabled permanent forced page directory syncing.\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ASMAtomicOrU32(&pVCpu->pgm.s.fSyncFlags, PGM_SYNC_ALWAYS);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Enabled permanent forced page directory syncing.\n");
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.
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync * @param pVM Pointer to the current VM (if any).
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync * @param paArgs Pointer to (readonly) array of arguments.
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync * @param cArgs Number of arguments in the array.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsyncstatic DECLCALLBACK(int) pgmR3CmdPhysToFile(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PVM pVM, PCDBGCVAR paArgs, unsigned cArgs, PDBGCVAR pResult)
82e90599291da476b2de7c8db33cfb0f2cbac774vboxsync * Validate input.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires a VM to be selected.\n");
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync 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);
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync * Open the output file and get the ram parameters.
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync int rc = RTFileOpen(&hFile, paArgs[0].u.pszString, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE);
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: RTFileOpen(,'%s',) -> %Rrc.\n", paArgs[0].u.pszString, rc);
fa7355597d7eba5b4ca8a23056ebe1b8fb306fdbvboxsync CFGMR3QueryU32Def(CFGMR3GetRoot(pVM), "RamHoleSize", &cbRamHole, MM_RAM_HOLE_SIZE_DEFAULT);
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync CFGMR3QueryU64Def(CFGMR3GetRoot(pVM), "RamSize", &cbRam, 0);
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync * Dump the physical memory, page by page.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pRam && pRam->GCPhys < GCPhysEnd && RT_SUCCESS(rc);
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync /* fill the gap */
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync rc = RTFileWrite(hFile, abZeroPg, PAGE_SIZE, NULL);
b40179b44fea65b72b2f226f62af1ed7bd3c48fcvboxsync 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);
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync rc = RTFileWrite(hFile, abZeroPg, PAGE_SIZE, NULL);
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: RTFileWrite -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
2634ec5cbf8f1fa0a968cd4664ead6df1fed730dvboxsync /* advance */
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Successfully saved physical memory to '%s'.\n", paArgs[0].u.pszString);
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync#endif /* VBOX_WITH_DEBUGGER */
eab582ddaaa130fc769ad00b09b81b3966817d3fvboxsync * pvUser argument of the pgmR3CheckIntegrity*Node callbacks.
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync bool fLeftToRight; /**< true: left-to-right; false: right-to-left. */
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * Validate a node in the physical handler tree.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @returns 0 on if ok, other wise 1.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pNode The handler node.
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync * @param pvUser pVM.
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsyncstatic DECLCALLBACK(int) pgmR3CheckIntegrityPhysHandlerNode(PAVLROGCPHYSNODECORE pNode, void *pvUser)
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync AssertReleaseMsg(pCur->Core.Key <= pCur->Core.KeyLast,("pCur=%p %RGp-%RGp %s\n", pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc));
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync || (pArgs->fLeftToRight ? pArgs->pPrevPhys->Core.KeyLast < pCur->Core.Key : pArgs->pPrevPhys->Core.KeyLast > pCur->Core.Key),
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync ("pPrevPhys=%p %RGp-%RGp %s\n"
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync " pCur=%p %RGp-%RGp %s\n",
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync pArgs->pPrevPhys, pArgs->pPrevPhys->Core.Key, pArgs->pPrevPhys->Core.KeyLast, pArgs->pPrevPhys->pszDesc,
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc));
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync * Validate a node in the virtual handler tree.
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync * @returns 0 on if ok, other wise 1.
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync * @param pNode The handler node.
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsync * @param pvUser pVM.
9f1e0743f565b1975bb4efd7311b30cfa0d3e384vboxsyncstatic 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",
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync pArgs->pPrevVirt, pArgs->pPrevVirt->Core.Key, pArgs->pPrevVirt->Core.KeyLast, pArgs->pPrevVirt->pszDesc,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc));
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync for (unsigned iPage = 0; iPage < pCur->cPages; iPage++)
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync AssertReleaseMsg(pCur->aPhysToVirt[iPage].offVirtHandler == -RT_OFFSETOF(PGMVIRTHANDLER, aPhysToVirt[iPage]),
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync ("pCur=%p %RGv-%RGv %s\n"
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync "iPage=%d offVirtHandle=%#x expected %#x\n",
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc,
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync iPage, pCur->aPhysToVirt[iPage].offVirtHandler, -RT_OFFSETOF(PGMVIRTHANDLER, aPhysToVirt[iPage])));
34e34d3656484dde89a9c7b57fcbf7048d2fdb13vboxsync * Validate a node in the virtual handler tree.
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync * @returns 0 on if ok, other wise 1.
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsync * @param pNode The handler node.
34e34d3656484dde89a9c7b57fcbf7048d2fdb13vboxsync * @param pvUser pVM.
c613f29bba8757289a5acf5a5dae7ee21b6b1ad5vboxsyncstatic DECLCALLBACK(int) pgmR3CheckIntegrityPhysToVirtHandlerNode(PAVLROGCPHYSNODECORE pNode, void *pvUser)
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync PPGMPHYS2VIRTHANDLER pCur = (PPGMPHYS2VIRTHANDLER)pNode;
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReleaseMsgReturn(!((uintptr_t)pCur & 3), ("\n"), 1);
ef4275be1971a6d17d45121d075a4f41659fa6c9vboxsync AssertReleaseMsgReturn(!(pCur->offVirtHandler & 3), ("\n"), 1);
ef4275be1971a6d17d45121d075a4f41659fa6c9vboxsync AssertReleaseMsg(pCur->Core.Key <= pCur->Core.KeyLast,("pCur=%p %RGp-%RGp\n", pCur, pCur->Core.Key, pCur->Core.KeyLast));
ef4275be1971a6d17d45121d075a4f41659fa6c9vboxsync || (pArgs->fLeftToRight ? pArgs->pPrevPhys2Virt->Core.KeyLast < pCur->Core.Key : pArgs->pPrevPhys2Virt->Core.KeyLast > pCur->Core.Key),
ef4275be1971a6d17d45121d075a4f41659fa6c9vboxsync ("pPrevPhys2Virt=%p %RGp-%RGp\n"
ef4275be1971a6d17d45121d075a4f41659fa6c9vboxsync " pCur=%p %RGp-%RGp\n",
ef4275be1971a6d17d45121d075a4f41659fa6c9vboxsync pArgs->pPrevPhys2Virt, pArgs->pPrevPhys2Virt->Core.Key, pArgs->pPrevPhys2Virt->Core.KeyLast,
ef4275be1971a6d17d45121d075a4f41659fa6c9vboxsync || (pArgs->fLeftToRight ? pArgs->pPrevPhys2Virt->Core.KeyLast < pCur->Core.Key : pArgs->pPrevPhys2Virt->Core.KeyLast > pCur->Core.Key),
ef4275be1971a6d17d45121d075a4f41659fa6c9vboxsync ("pPrevPhys2Virt=%p %RGp-%RGp\n"
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync " pCur=%p %RGp-%RGp\n",
ef4275be1971a6d17d45121d075a4f41659fa6c9vboxsync pArgs->pPrevPhys2Virt, pArgs->pPrevPhys2Virt->Core.Key, pArgs->pPrevPhys2Virt->Core.KeyLast,
ef4275be1971a6d17d45121d075a4f41659fa6c9vboxsync AssertReleaseMsg((pCur->offNextAlias & (PGMPHYS2VIRTHANDLER_IN_TREE | PGMPHYS2VIRTHANDLER_IS_HEAD)) == (PGMPHYS2VIRTHANDLER_IN_TREE | PGMPHYS2VIRTHANDLER_IS_HEAD),
ef4275be1971a6d17d45121d075a4f41659fa6c9vboxsync ("pCur=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
9f9a20823b87e89c1b5cb45eb9b5699b29bfefebvboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->offVirtHandler, pCur->offNextAlias));
ef4275be1971a6d17d45121d075a4f41659fa6c9vboxsync if (pCur->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK)
ef4275be1971a6d17d45121d075a4f41659fa6c9vboxsync pCur2 = (PPGMPHYS2VIRTHANDLER)((intptr_t)pCur + (pCur->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK));
ef4275be1971a6d17d45121d075a4f41659fa6c9vboxsync (" pCur=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->offVirtHandler, pCur->offNextAlias));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReleaseMsg((pCur2->offNextAlias & (PGMPHYS2VIRTHANDLER_IN_TREE | PGMPHYS2VIRTHANDLER_IS_HEAD)) == PGMPHYS2VIRTHANDLER_IN_TREE,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync (" pCur=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n"
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync "pCur2=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->offVirtHandler, pCur->offNextAlias,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCur2, pCur2->Core.Key, pCur2->Core.KeyLast, pCur2->offVirtHandler, pCur2->offNextAlias));
8f7bc6ad2b7bbcb4b3b96248cd2478e45f2e3b88vboxsync AssertReleaseMsg((pCur2->Core.Key ^ pCur->Core.Key) < PAGE_SIZE,
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync (" pCur=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n"
8f7bc6ad2b7bbcb4b3b96248cd2478e45f2e3b88vboxsync "pCur2=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->offVirtHandler, pCur->offNextAlias,
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync pCur2, pCur2->Core.Key, pCur2->Core.KeyLast, pCur2->offVirtHandler, pCur2->offNextAlias));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync AssertReleaseMsg((pCur2->Core.KeyLast ^ pCur->Core.KeyLast) < PAGE_SIZE,
1f8ba3bc3e0f62b02e3dc7440cdd6519e8c64e30vboxsync (" pCur=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n"
ef4275be1971a6d17d45121d075a4f41659fa6c9vboxsync "pCur2=%p:{.Core.Key=%RGp, .Core.KeyLast=%RGp, .offVirtHandler=%#RX32, .offNextAlias=%#RX32}\n",
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->offVirtHandler, pCur->offNextAlias,
9f9a20823b87e89c1b5cb45eb9b5699b29bfefebvboxsync pCur2, pCur2->Core.Key, pCur2->Core.KeyLast, pCur2->offVirtHandler, pCur2->offNextAlias));
d408b82da0773c7e8cd4b3a01cb8a065a2c73a2dvboxsync if (!(pCur2->offNextAlias & PGMPHYS2VIRTHANDLER_OFF_MASK))
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync * Perform an integrity check on the PGM component.
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync * @returns VINF_SUCCESS if everything is fine.
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync * @returns VBox error status after asserting on integrity breach.
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync * @param pVM The VM handle.
e4ea543752422f1139923e3e506c625b0a1827c5vboxsync AssertReleaseReturn(pVM->pgm.s.offVM, VERR_INTERNAL_ERROR);
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync * Check the trees.
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync const static PGMCHECKINTARGS s_LeftToRight = { true, NULL, NULL, NULL, pVM };
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync const static PGMCHECKINTARGS s_RightToLeft = { false, NULL, NULL, NULL, pVM };
9673b0b804d0b0f801f377c6371600e92071241fvboxsync cErrors += RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesR3->PhysHandlers, true, pgmR3CheckIntegrityPhysHandlerNode, &Args);
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync cErrors += RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesR3->PhysHandlers, false, pgmR3CheckIntegrityPhysHandlerNode, &Args);
40f47bc231ff6c86a7ddc3295eed7010e889e78avboxsync cErrors += RTAvlroGCPtrDoWithAll( &pVM->pgm.s.pTreesR3->VirtHandlers, true, pgmR3CheckIntegrityVirtHandlerNode, &Args);
3cac8f8c6923a3a89ecfccda5e89ad75f48658e0vboxsync cErrors += RTAvlroGCPtrDoWithAll( &pVM->pgm.s.pTreesR3->VirtHandlers, false, pgmR3CheckIntegrityVirtHandlerNode, &Args);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync cErrors += RTAvlroGCPtrDoWithAll( &pVM->pgm.s.pTreesR3->HyperVirtHandlers, true, pgmR3CheckIntegrityVirtHandlerNode, &Args);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync cErrors += RTAvlroGCPtrDoWithAll( &pVM->pgm.s.pTreesR3->HyperVirtHandlers, false, pgmR3CheckIntegrityVirtHandlerNode, &Args);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync cErrors += RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesR3->PhysToVirtHandlers, true, pgmR3CheckIntegrityPhysToVirtHandlerNode, &Args);
61fa69e2bc9fc9e7490feed1c020273f3ddb238dvboxsync cErrors += RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesR3->PhysToVirtHandlers, false, pgmR3CheckIntegrityPhysToVirtHandlerNode, &Args);