VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/PGM.cpp@ 92780

Last change on this file since 92780 was 92717, checked in by vboxsync, 3 years ago

VMM/PGM: Driverless requires the simplified memory mode. Must also fake host physical address for the MMIO and ZERO pages, or we'll end up asserting elsewhere in PGM for to good reason. bugref:10138

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 138.8 KB
Line 
1/* $Id: PGM.cpp 92717 2021-12-02 21:43:46Z vboxsync $ */
2/** @file
3 * PGM - Page Manager and Monitor. (Mixing stuff here, not good?)
4 */
5
6/*
7 * Copyright (C) 2006-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/** @page pg_pgm PGM - The Page Manager and Monitor
20 *
21 * @sa @ref grp_pgm
22 * @subpage pg_pgm_pool
23 * @subpage pg_pgm_phys
24 *
25 *
26 * @section sec_pgm_modes Paging Modes
27 *
28 * There are three memory contexts: Host Context (HC), Guest Context (GC)
29 * and intermediate context. When talking about paging HC can also be referred
30 * to as "host paging", and GC referred to as "shadow paging".
31 *
32 * We define three basic paging modes: 32-bit, PAE and AMD64. The host paging mode
33 * is defined by the host operating system. The mode used in the shadow paging mode
34 * depends on the host paging mode and what the mode the guest is currently in. The
35 * following relation between the two is defined:
36 *
37 * @verbatim
38 Host > 32-bit | PAE | AMD64 |
39 Guest | | | |
40 ==v================================
41 32-bit 32-bit PAE PAE
42 -------|--------|--------|--------|
43 PAE PAE PAE PAE
44 -------|--------|--------|--------|
45 AMD64 AMD64 AMD64 AMD64
46 -------|--------|--------|--------| @endverbatim
47 *
48 * All configuration except those in the diagonal (upper left) are expected to
49 * require special effort from the switcher (i.e. a bit slower).
50 *
51 *
52 *
53 *
54 * @section sec_pgm_shw The Shadow Memory Context
55 *
56 *
57 * [..]
58 *
59 * Because of guest context mappings requires PDPT and PML4 entries to allow
60 * writing on AMD64, the two upper levels will have fixed flags whatever the
61 * guest is thinking of using there. So, when shadowing the PD level we will
62 * calculate the effective flags of PD and all the higher levels. In legacy
63 * PAE mode this only applies to the PWT and PCD bits (the rest are
64 * ignored/reserved/MBZ). We will ignore those bits for the present.
65 *
66 *
67 *
68 * @section sec_pgm_int The Intermediate Memory Context
69 *
70 * The world switch goes thru an intermediate memory context which purpose it is
71 * to provide different mappings of the switcher code. All guest mappings are also
72 * present in this context.
73 *
74 * The switcher code is mapped at the same location as on the host, at an
75 * identity mapped location (physical equals virtual address), and at the
76 * hypervisor location. The identity mapped location is for when the world
77 * switches that involves disabling paging.
78 *
79 * PGM maintain page tables for 32-bit, PAE and AMD64 paging modes. This
80 * simplifies switching guest CPU mode and consistency at the cost of more
81 * code to do the work. All memory use for those page tables is located below
82 * 4GB (this includes page tables for guest context mappings).
83 *
84 * Note! The intermediate memory context is also used for 64-bit guest
85 * execution on 32-bit hosts. Because we need to load 64-bit registers
86 * prior to switching to guest context, we need to be in 64-bit mode
87 * first. So, HM has some 64-bit worker routines in VMMRC.rc that get
88 * invoked via the special world switcher code in LegacyToAMD64.asm.
89 *
90 *
91 * @subsection subsec_pgm_int_gc Guest Context Mappings
92 *
93 * During assignment and relocation of a guest context mapping the intermediate
94 * memory context is used to verify the new location.
95 *
96 * Guest context mappings are currently restricted to below 4GB, for reasons
97 * of simplicity. This may change when we implement AMD64 support.
98 *
99 *
100 *
101 *
102 * @section sec_pgm_misc Misc
103 *
104 *
105 * @subsection sec_pgm_misc_A20 The A20 Gate
106 *
107 * PGM implements the A20 gate masking when translating a virtual guest address
108 * into a physical address for CPU access, i.e. PGMGstGetPage (and friends) and
109 * the code reading the guest page table entries during shadowing. The masking
110 * is done consistenly for all CPU modes, paged ones included. Large pages are
111 * also masked correctly. (On current CPUs, experiments indicates that AMD does
112 * not apply A20M in paged modes and intel only does it for the 2nd MB of
113 * memory.)
114 *
115 * The A20 gate implementation is per CPU core. It can be configured on a per
116 * core basis via the keyboard device and PC architecture device. This is
117 * probably not exactly how real CPUs do it, but SMP and A20 isn't a place where
118 * guest OSes try pushing things anyway, so who cares. (On current real systems
119 * the A20M signal is probably only sent to the boot CPU and it affects all
120 * thread and probably all cores in that package.)
121 *
122 * The keyboard device and the PC architecture device doesn't OR their A20
123 * config bits together, rather they are currently implemented such that they
124 * mirror the CPU state. So, flipping the bit in either of them will change the
125 * A20 state. (On real hardware the bits of the two devices should probably be
126 * ORed together to indicate enabled, i.e. both needs to be cleared to disable
127 * A20 masking.)
128 *
129 * The A20 state will change immediately, transmeta fashion. There is no delays
130 * due to buses, wiring or other physical stuff. (On real hardware there are
131 * normally delays, the delays differs between the two devices and probably also
132 * between chipsets and CPU generations. Note that it's said that transmeta CPUs
133 * does the change immediately like us, they apparently intercept/handles the
134 * port accesses in microcode. Neat.)
135 *
136 * @sa http://en.wikipedia.org/wiki/A20_line#The_80286_and_the_high_memory_area
137 *
138 *
139 * @subsection subsec_pgm_misc_diff Differences Between Legacy PAE and Long Mode PAE
140 *
141 * The differences between legacy PAE and long mode PAE are:
142 * -# PDPE bits 1, 2, 5 and 6 are defined differently. In leagcy mode they are
143 * all marked down as must-be-zero, while in long mode 1, 2 and 5 have the
144 * usual meanings while 6 is ignored (AMD). This means that upon switching to
145 * legacy PAE mode we'll have to clear these bits and when going to long mode
146 * they must be set. This applies to both intermediate and shadow contexts,
147 * however we don't need to do it for the intermediate one since we're
148 * executing with CR0.WP at that time.
149 * -# CR3 allows a 32-byte aligned address in legacy mode, while in long mode
150 * a page aligned one is required.
151 *
152 *
153 * @section sec_pgm_handlers Access Handlers
154 *
155 * Placeholder.
156 *
157 *
158 * @subsection sec_pgm_handlers_phys Physical Access Handlers
159 *
160 * Placeholder.
161 *
162 *
163 * @subsection sec_pgm_handlers_virt Virtual Access Handlers (obsolete)
164 *
165 * We currently implement three types of virtual access handlers: ALL, WRITE
166 * and HYPERVISOR (WRITE). See PGMVIRTHANDLERKIND for some more details.
167 *
168 * The HYPERVISOR access handlers is kept in a separate tree since it doesn't apply
169 * to physical pages (PGMTREES::HyperVirtHandlers) and only needs to be consulted in
170 * a special \#PF case. The ALL and WRITE are in the PGMTREES::VirtHandlers tree, the
171 * rest of this section is going to be about these handlers.
172 *
173 * We'll go thru the life cycle of a handler and try make sense of it all, don't know
174 * how successful this is gonna be...
175 *
176 * 1. A handler is registered thru the PGMR3HandlerVirtualRegister and
177 * PGMHandlerVirtualRegisterEx APIs. We check for conflicting virtual handlers
178 * and create a new node that is inserted into the AVL tree (range key). Then
179 * a full PGM resync is flagged (clear pool, sync cr3, update virtual bit of PGMPAGE).
180 *
181 * 2. The following PGMSyncCR3/SyncCR3 operation will first make invoke HandlerVirtualUpdate.
182 *
183 * 2a. HandlerVirtualUpdate will will lookup all the pages covered by virtual handlers
184 * via the current guest CR3 and update the physical page -> virtual handler
185 * translation. Needless to say, this doesn't exactly scale very well. If any changes
186 * are detected, it will flag a virtual bit update just like we did on registration.
187 * PGMPHYS pages with changes will have their virtual handler state reset to NONE.
188 *
189 * 2b. The virtual bit update process will iterate all the pages covered by all the
190 * virtual handlers and update the PGMPAGE virtual handler state to the max of all
191 * virtual handlers on that page.
192 *
193 * 2c. Back in SyncCR3 we will now flush the entire shadow page cache to make sure
194 * we don't miss any alias mappings of the monitored pages.
195 *
196 * 2d. SyncCR3 will then proceed with syncing the CR3 table.
197 *
198 * 3. \#PF(np,read) on a page in the range. This will cause it to be synced
199 * read-only and resumed if it's a WRITE handler. If it's an ALL handler we
200 * will call the handlers like in the next step. If the physical mapping has
201 * changed we will - some time in the future - perform a handler callback
202 * (optional) and update the physical -> virtual handler cache.
203 *
204 * 4. \#PF(,write) on a page in the range. This will cause the handler to
205 * be invoked.
206 *
207 * 5. The guest invalidates the page and changes the physical backing or
208 * unmaps it. This should cause the invalidation callback to be invoked
209 * (it might not yet be 100% perfect). Exactly what happens next... is
210 * this where we mess up and end up out of sync for a while?
211 *
212 * 6. The handler is deregistered by the client via PGMHandlerVirtualDeregister.
213 * We will then set all PGMPAGEs in the physical -> virtual handler cache for
214 * this handler to NONE and trigger a full PGM resync (basically the same
215 * as int step 1). Which means 2 is executed again.
216 *
217 *
218 * @subsubsection sub_sec_pgm_handler_virt_todo TODOs
219 *
220 * There is a bunch of things that needs to be done to make the virtual handlers
221 * work 100% correctly and work more efficiently.
222 *
223 * The first bit hasn't been implemented yet because it's going to slow the
224 * whole mess down even more, and besides it seems to be working reliably for
225 * our current uses. OTOH, some of the optimizations might end up more or less
226 * implementing the missing bits, so we'll see.
227 *
228 * On the optimization side, the first thing to do is to try avoid unnecessary
229 * cache flushing. Then try team up with the shadowing code to track changes
230 * in mappings by means of access to them (shadow in), updates to shadows pages,
231 * invlpg, and shadow PT discarding (perhaps).
232 *
233 * Some idea that have popped up for optimization for current and new features:
234 * - bitmap indicating where there are virtual handlers installed.
235 * (4KB => 2**20 pages, page 2**12 => covers 32-bit address space 1:1!)
236 * - Further optimize this by min/max (needs min/max avl getters).
237 * - Shadow page table entry bit (if any left)?
238 *
239 */
240
241
242/** @page pg_pgm_phys PGM Physical Guest Memory Management
243 *
244 *
245 * Objectives:
246 * - Guest RAM over-commitment using memory ballooning,
247 * zero pages and general page sharing.
248 * - Moving or mirroring a VM onto a different physical machine.
249 *
250 *
251 * @section sec_pgmPhys_Definitions Definitions
252 *
253 * Allocation chunk - A RTR0MemObjAllocPhysNC or RTR0MemObjAllocPhys allocate
254 * memory object and the tracking machinery associated with it.
255 *
256 *
257 *
258 *
259 * @section sec_pgmPhys_AllocPage Allocating a page.
260 *
261 * Initially we map *all* guest memory to the (per VM) zero page, which
262 * means that none of the read functions will cause pages to be allocated.
263 *
264 * Exception, access bit in page tables that have been shared. This must
265 * be handled, but we must also make sure PGMGst*Modify doesn't make
266 * unnecessary modifications.
267 *
268 * Allocation points:
269 * - PGMPhysSimpleWriteGCPhys and PGMPhysWrite.
270 * - Replacing a zero page mapping at \#PF.
271 * - Replacing a shared page mapping at \#PF.
272 * - ROM registration (currently MMR3RomRegister).
273 * - VM restore (pgmR3Load).
274 *
275 * For the first three it would make sense to keep a few pages handy
276 * until we've reached the max memory commitment for the VM.
277 *
278 * For the ROM registration, we know exactly how many pages we need
279 * and will request these from ring-0. For restore, we will save
280 * the number of non-zero pages in the saved state and allocate
281 * them up front. This would allow the ring-0 component to refuse
282 * the request if the isn't sufficient memory available for VM use.
283 *
284 * Btw. for both ROM and restore allocations we won't be requiring
285 * zeroed pages as they are going to be filled instantly.
286 *
287 *
288 * @section sec_pgmPhys_FreePage Freeing a page
289 *
290 * There are a few points where a page can be freed:
291 * - After being replaced by the zero page.
292 * - After being replaced by a shared page.
293 * - After being ballooned by the guest additions.
294 * - At reset.
295 * - At restore.
296 *
297 * When freeing one or more pages they will be returned to the ring-0
298 * component and replaced by the zero page.
299 *
300 * The reasoning for clearing out all the pages on reset is that it will
301 * return us to the exact same state as on power on, and may thereby help
302 * us reduce the memory load on the system. Further it might have a
303 * (temporary) positive influence on memory fragmentation (@see subsec_pgmPhys_Fragmentation).
304 *
305 * On restore, as mention under the allocation topic, pages should be
306 * freed / allocated depending on how many is actually required by the
307 * new VM state. The simplest approach is to do like on reset, and free
308 * all non-ROM pages and then allocate what we need.
309 *
310 * A measure to prevent some fragmentation, would be to let each allocation
311 * chunk have some affinity towards the VM having allocated the most pages
312 * from it. Also, try make sure to allocate from allocation chunks that
313 * are almost full. Admittedly, both these measures might work counter to
314 * our intentions and its probably not worth putting a lot of effort,
315 * cpu time or memory into this.
316 *
317 *
318 * @section sec_pgmPhys_SharePage Sharing a page
319 *
320 * The basic idea is that there there will be a idle priority kernel
321 * thread walking the non-shared VM pages hashing them and looking for
322 * pages with the same checksum. If such pages are found, it will compare
323 * them byte-by-byte to see if they actually are identical. If found to be
324 * identical it will allocate a shared page, copy the content, check that
325 * the page didn't change while doing this, and finally request both the
326 * VMs to use the shared page instead. If the page is all zeros (special
327 * checksum and byte-by-byte check) it will request the VM that owns it
328 * to replace it with the zero page.
329 *
330 * To make this efficient, we will have to make sure not to try share a page
331 * that will change its contents soon. This part requires the most work.
332 * A simple idea would be to request the VM to write monitor the page for
333 * a while to make sure it isn't modified any time soon. Also, it may
334 * make sense to skip pages that are being write monitored since this
335 * information is readily available to the thread if it works on the
336 * per-VM guest memory structures (presently called PGMRAMRANGE).
337 *
338 *
339 * @section sec_pgmPhys_Fragmentation Fragmentation Concerns and Counter Measures
340 *
341 * The pages are organized in allocation chunks in ring-0, this is a necessity
342 * if we wish to have an OS agnostic approach to this whole thing. (On Linux we
343 * could easily work on a page-by-page basis if we liked. Whether this is possible
344 * or efficient on NT I don't quite know.) Fragmentation within these chunks may
345 * become a problem as part of the idea here is that we wish to return memory to
346 * the host system.
347 *
348 * For instance, starting two VMs at the same time, they will both allocate the
349 * guest memory on-demand and if permitted their page allocations will be
350 * intermixed. Shut down one of the two VMs and it will be difficult to return
351 * any memory to the host system because the page allocation for the two VMs are
352 * mixed up in the same allocation chunks.
353 *
354 * To further complicate matters, when pages are freed because they have been
355 * ballooned or become shared/zero the whole idea is that the page is supposed
356 * to be reused by another VM or returned to the host system. This will cause
357 * allocation chunks to contain pages belonging to different VMs and prevent
358 * returning memory to the host when one of those VM shuts down.
359 *
360 * The only way to really deal with this problem is to move pages. This can
361 * either be done at VM shutdown and or by the idle priority worker thread
362 * that will be responsible for finding sharable/zero pages. The mechanisms
363 * involved for coercing a VM to move a page (or to do it for it) will be
364 * the same as when telling it to share/zero a page.
365 *
366 *
367 * @section sec_pgmPhys_Tracking Tracking Structures And Their Cost
368 *
369 * There's a difficult balance between keeping the per-page tracking structures
370 * (global and guest page) easy to use and keeping them from eating too much
371 * memory. We have limited virtual memory resources available when operating in
372 * 32-bit kernel space (on 64-bit there'll it's quite a different story). The
373 * tracking structures will be attempted designed such that we can deal with up
374 * to 32GB of memory on a 32-bit system and essentially unlimited on 64-bit ones.
375 *
376 *
377 * @subsection subsec_pgmPhys_Tracking_Kernel Kernel Space
378 *
379 * @see pg_GMM
380 *
381 * @subsection subsec_pgmPhys_Tracking_PerVM Per-VM
382 *
383 * Fixed info is the physical address of the page (HCPhys) and the page id
384 * (described above). Theoretically we'll need 48(-12) bits for the HCPhys part.
385 * Today we've restricting ourselves to 40(-12) bits because this is the current
386 * restrictions of all AMD64 implementations (I think Barcelona will up this
387 * to 48(-12) bits, not that it really matters) and I needed the bits for
388 * tracking mappings of a page. 48-12 = 36. That leaves 28 bits, which means a
389 * decent range for the page id: 2^(28+12) = 1024TB.
390 *
391 * In additions to these, we'll have to keep maintaining the page flags as we
392 * currently do. Although it wouldn't harm to optimize these quite a bit, like
393 * for instance the ROM shouldn't depend on having a write handler installed
394 * in order for it to become read-only. A RO/RW bit should be considered so
395 * that the page syncing code doesn't have to mess about checking multiple
396 * flag combinations (ROM || RW handler || write monitored) in order to
397 * figure out how to setup a shadow PTE. But this of course, is second
398 * priority at present. Current this requires 12 bits, but could probably
399 * be optimized to ~8.
400 *
401 * Then there's the 24 bits used to track which shadow page tables are
402 * currently mapping a page for the purpose of speeding up physical
403 * access handlers, and thereby the page pool cache. More bit for this
404 * purpose wouldn't hurt IIRC.
405 *
406 * Then there is a new bit in which we need to record what kind of page
407 * this is, shared, zero, normal or write-monitored-normal. This'll
408 * require 2 bits. One bit might be needed for indicating whether a
409 * write monitored page has been written to. And yet another one or
410 * two for tracking migration status. 3-4 bits total then.
411 *
412 * Whatever is left will can be used to record the sharabilitiy of a
413 * page. The page checksum will not be stored in the per-VM table as
414 * the idle thread will not be permitted to do modifications to it.
415 * It will instead have to keep its own working set of potentially
416 * shareable pages and their check sums and stuff.
417 *
418 * For the present we'll keep the current packing of the
419 * PGMRAMRANGE::aHCPhys to keep the changes simple, only of course,
420 * we'll have to change it to a struct with a total of 128-bits at
421 * our disposal.
422 *
423 * The initial layout will be like this:
424 * @verbatim
425 RTHCPHYS HCPhys; The current stuff.
426 63:40 Current shadow PT tracking stuff.
427 39:12 The physical page frame number.
428 11:0 The current flags.
429 uint32_t u28PageId : 28; The page id.
430 uint32_t u2State : 2; The page state { zero, shared, normal, write monitored }.
431 uint32_t fWrittenTo : 1; Whether a write monitored page was written to.
432 uint32_t u1Reserved : 1; Reserved for later.
433 uint32_t u32Reserved; Reserved for later, mostly sharing stats.
434 @endverbatim
435 *
436 * The final layout will be something like this:
437 * @verbatim
438 RTHCPHYS HCPhys; The current stuff.
439 63:48 High page id (12+).
440 47:12 The physical page frame number.
441 11:0 Low page id.
442 uint32_t fReadOnly : 1; Whether it's readonly page (rom or monitored in some way).
443 uint32_t u3Type : 3; The page type {RESERVED, MMIO, MMIO2, ROM, shadowed ROM, RAM}.
444 uint32_t u2PhysMon : 2; Physical access handler type {none, read, write, all}.
445 uint32_t u2VirtMon : 2; Virtual access handler type {none, read, write, all}..
446 uint32_t u2State : 2; The page state { zero, shared, normal, write monitored }.
447 uint32_t fWrittenTo : 1; Whether a write monitored page was written to.
448 uint32_t u20Reserved : 20; Reserved for later, mostly sharing stats.
449 uint32_t u32Tracking; The shadow PT tracking stuff, roughly.
450 @endverbatim
451 *
452 * Cost wise, this means we'll double the cost for guest memory. There isn't anyway
453 * around that I'm afraid. It means that the cost of dealing out 32GB of memory
454 * to one or more VMs is: (32GB >> PAGE_SHIFT) * 16 bytes, or 128MBs. Or another
455 * example, the VM heap cost when assigning 1GB to a VM will be: 4MB.
456 *
457 * A couple of cost examples for the total cost per-VM + kernel.
458 * 32-bit Windows and 32-bit linux:
459 * 1GB guest ram, 256K pages: 4MB + 2MB(+) = 6MB
460 * 4GB guest ram, 1M pages: 16MB + 8MB(+) = 24MB
461 * 32GB guest ram, 8M pages: 128MB + 64MB(+) = 192MB
462 * 64-bit Windows and 64-bit linux:
463 * 1GB guest ram, 256K pages: 4MB + 3MB(+) = 7MB
464 * 4GB guest ram, 1M pages: 16MB + 12MB(+) = 28MB
465 * 32GB guest ram, 8M pages: 128MB + 96MB(+) = 224MB
466 *
467 * UPDATE - 2007-09-27:
468 * Will need a ballooned flag/state too because we cannot
469 * trust the guest 100% and reporting the same page as ballooned more
470 * than once will put the GMM off balance.
471 *
472 *
473 * @section sec_pgmPhys_Serializing Serializing Access
474 *
475 * Initially, we'll try a simple scheme:
476 *
477 * - The per-VM RAM tracking structures (PGMRAMRANGE) is only modified
478 * by the EMT thread of that VM while in the pgm critsect.
479 * - Other threads in the VM process that needs to make reliable use of
480 * the per-VM RAM tracking structures will enter the critsect.
481 * - No process external thread or kernel thread will ever try enter
482 * the pgm critical section, as that just won't work.
483 * - The idle thread (and similar threads) doesn't not need 100% reliable
484 * data when performing it tasks as the EMT thread will be the one to
485 * do the actual changes later anyway. So, as long as it only accesses
486 * the main ram range, it can do so by somehow preventing the VM from
487 * being destroyed while it works on it...
488 *
489 * - The over-commitment management, including the allocating/freeing
490 * chunks, is serialized by a ring-0 mutex lock (a fast one since the
491 * more mundane mutex implementation is broken on Linux).
492 * - A separate mutex is protecting the set of allocation chunks so
493 * that pages can be shared or/and freed up while some other VM is
494 * allocating more chunks. This mutex can be take from under the other
495 * one, but not the other way around.
496 *
497 *
498 * @section sec_pgmPhys_Request VM Request interface
499 *
500 * When in ring-0 it will become necessary to send requests to a VM so it can
501 * for instance move a page while defragmenting during VM destroy. The idle
502 * thread will make use of this interface to request VMs to setup shared
503 * pages and to perform write monitoring of pages.
504 *
505 * I would propose an interface similar to the current VMReq interface, similar
506 * in that it doesn't require locking and that the one sending the request may
507 * wait for completion if it wishes to. This shouldn't be very difficult to
508 * realize.
509 *
510 * The requests themselves are also pretty simple. They are basically:
511 * -# Check that some precondition is still true.
512 * -# Do the update.
513 * -# Update all shadow page tables involved with the page.
514 *
515 * The 3rd step is identical to what we're already doing when updating a
516 * physical handler, see pgmHandlerPhysicalSetRamFlagsAndFlushShadowPTs.
517 *
518 *
519 *
520 * @section sec_pgmPhys_MappingCaches Mapping Caches
521 *
522 * In order to be able to map in and out memory and to be able to support
523 * guest with more RAM than we've got virtual address space, we'll employing
524 * a mapping cache. Normally ring-0 and ring-3 can share the same cache,
525 * however on 32-bit darwin the ring-0 code is running in a different memory
526 * context and therefore needs a separate cache. In raw-mode context we also
527 * need a separate cache. The 32-bit darwin mapping cache and the one for
528 * raw-mode context share a lot of code, see PGMRZDYNMAP.
529 *
530 *
531 * @subsection subsec_pgmPhys_MappingCaches_R3 Ring-3
532 *
533 * We've considered implementing the ring-3 mapping cache page based but found
534 * that this was bother some when one had to take into account TLBs+SMP and
535 * portability (missing the necessary APIs on several platforms). There were
536 * also some performance concerns with this approach which hadn't quite been
537 * worked out.
538 *
539 * Instead, we'll be mapping allocation chunks into the VM process. This simplifies
540 * matters greatly quite a bit since we don't need to invent any new ring-0 stuff,
541 * only some minor RTR0MEMOBJ mapping stuff. The main concern here is that mapping
542 * compared to the previous idea is that mapping or unmapping a 1MB chunk is more
543 * costly than a single page, although how much more costly is uncertain. We'll
544 * try address this by using a very big cache, preferably bigger than the actual
545 * VM RAM size if possible. The current VM RAM sizes should give some idea for
546 * 32-bit boxes, while on 64-bit we can probably get away with employing an
547 * unlimited cache.
548 *
549 * The cache have to parts, as already indicated, the ring-3 side and the
550 * ring-0 side.
551 *
552 * The ring-0 will be tied to the page allocator since it will operate on the
553 * memory objects it contains. It will therefore require the first ring-0 mutex
554 * discussed in @ref sec_pgmPhys_Serializing. We some double house keeping wrt
555 * to who has mapped what I think, since both VMMR0.r0 and RTR0MemObj will keep
556 * track of mapping relations
557 *
558 * The ring-3 part will be protected by the pgm critsect. For simplicity, we'll
559 * require anyone that desires to do changes to the mapping cache to do that
560 * from within this critsect. Alternatively, we could employ a separate critsect
561 * for serializing changes to the mapping cache as this would reduce potential
562 * contention with other threads accessing mappings unrelated to the changes
563 * that are in process. We can see about this later, contention will show
564 * up in the statistics anyway, so it'll be simple to tell.
565 *
566 * The organization of the ring-3 part will be very much like how the allocation
567 * chunks are organized in ring-0, that is in an AVL tree by chunk id. To avoid
568 * having to walk the tree all the time, we'll have a couple of lookaside entries
569 * like in we do for I/O ports and MMIO in IOM.
570 *
571 * The simplified flow of a PGMPhysRead/Write function:
572 * -# Enter the PGM critsect.
573 * -# Lookup GCPhys in the ram ranges and get the Page ID.
574 * -# Calc the Allocation Chunk ID from the Page ID.
575 * -# Check the lookaside entries and then the AVL tree for the Chunk ID.
576 * If not found in cache:
577 * -# Call ring-0 and request it to be mapped and supply
578 * a chunk to be unmapped if the cache is maxed out already.
579 * -# Insert the new mapping into the AVL tree (id + R3 address).
580 * -# Update the relevant lookaside entry and return the mapping address.
581 * -# Do the read/write according to monitoring flags and everything.
582 * -# Leave the critsect.
583 *
584 *
585 * @section sec_pgmPhys_Changes Changes
586 *
587 * Breakdown of the changes involved?
588 */
589
590
591/*********************************************************************************************************************************
592* Header Files *
593*********************************************************************************************************************************/
594#define LOG_GROUP LOG_GROUP_PGM
595#define VBOX_WITHOUT_PAGING_BIT_FIELDS /* 64-bit bitfields are just asking for trouble. See @bugref{9841} and others. */
596#include <VBox/vmm/dbgf.h>
597#include <VBox/vmm/pgm.h>
598#include <VBox/vmm/cpum.h>
599#include <VBox/vmm/iom.h>
600#include <VBox/sup.h>
601#include <VBox/vmm/mm.h>
602#include <VBox/vmm/em.h>
603#include <VBox/vmm/stam.h>
604#include <VBox/vmm/selm.h>
605#include <VBox/vmm/ssm.h>
606#include <VBox/vmm/hm.h>
607#include "PGMInternal.h"
608#include <VBox/vmm/vm.h>
609#include <VBox/vmm/uvm.h>
610#include "PGMInline.h"
611
612#include <VBox/dbg.h>
613#include <VBox/param.h>
614#include <VBox/err.h>
615
616#include <iprt/asm.h>
617#include <iprt/asm-amd64-x86.h>
618#include <iprt/assert.h>
619#include <iprt/env.h>
620#include <iprt/mem.h>
621#include <iprt/file.h>
622#include <iprt/string.h>
623#include <iprt/thread.h>
624#ifdef RT_OS_LINUX
625# include <iprt/linux/sysfs.h>
626#endif
627
628
629/*********************************************************************************************************************************
630* Structures and Typedefs *
631*********************************************************************************************************************************/
632/**
633 * Argument package for pgmR3RElocatePhysHnadler, pgmR3RelocateVirtHandler and
634 * pgmR3RelocateHyperVirtHandler.
635 */
636typedef struct PGMRELOCHANDLERARGS
637{
638 RTGCINTPTR offDelta;
639 PVM pVM;
640} PGMRELOCHANDLERARGS;
641/** Pointer to a page access handlere relocation argument package. */
642typedef PGMRELOCHANDLERARGS const *PCPGMRELOCHANDLERARGS;
643
644
645/*********************************************************************************************************************************
646* Internal Functions *
647*********************************************************************************************************************************/
648static int pgmR3InitPaging(PVM pVM);
649static int pgmR3InitStats(PVM pVM);
650static DECLCALLBACK(void) pgmR3PhysInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
651static DECLCALLBACK(void) pgmR3InfoMode(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
652static DECLCALLBACK(void) pgmR3InfoCr3(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
653#ifdef VBOX_STRICT
654static FNVMATSTATE pgmR3ResetNoMorePhysWritesFlag;
655#endif
656
657#ifdef VBOX_WITH_DEBUGGER
658static FNDBGCCMD pgmR3CmdError;
659static FNDBGCCMD pgmR3CmdSync;
660static FNDBGCCMD pgmR3CmdSyncAlways;
661# ifdef VBOX_STRICT
662static FNDBGCCMD pgmR3CmdAssertCR3;
663# endif
664static FNDBGCCMD pgmR3CmdPhysToFile;
665#endif
666
667
668/*********************************************************************************************************************************
669* Global Variables *
670*********************************************************************************************************************************/
671#ifdef VBOX_WITH_DEBUGGER
672/** Argument descriptors for '.pgmerror' and '.pgmerroroff'. */
673static const DBGCVARDESC g_aPgmErrorArgs[] =
674{
675 /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
676 { 0, 1, DBGCVAR_CAT_STRING, 0, "where", "Error injection location." },
677};
678
679static const DBGCVARDESC g_aPgmPhysToFileArgs[] =
680{
681 /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
682 { 1, 1, DBGCVAR_CAT_STRING, 0, "file", "The file name." },
683 { 0, 1, DBGCVAR_CAT_STRING, 0, "nozero", "If present, zero pages are skipped." },
684};
685
686# ifdef DEBUG_sandervl
687static const DBGCVARDESC g_aPgmCountPhysWritesArgs[] =
688{
689 /* cTimesMin, cTimesMax, enmCategory, fFlags, pszName, pszDescription */
690 { 1, 1, DBGCVAR_CAT_STRING, 0, "enabled", "on/off." },
691 { 1, 1, DBGCVAR_CAT_NUMBER_NO_RANGE, 0, "interval", "Interval in ms." },
692};
693# endif
694
695/** Command descriptors. */
696static const DBGCCMD g_aCmds[] =
697{
698 /* pszCmd, cArgsMin, cArgsMax, paArgDesc, cArgDescs, fFlags, pfnHandler pszSyntax, ....pszDescription */
699 { "pgmsync", 0, 0, NULL, 0, 0, pgmR3CmdSync, "", "Sync the CR3 page." },
700 { "pgmerror", 0, 1, &g_aPgmErrorArgs[0], 1, 0, pgmR3CmdError, "", "Enables inject runtime of errors into parts of PGM." },
701 { "pgmerroroff", 0, 1, &g_aPgmErrorArgs[0], 1, 0, pgmR3CmdError, "", "Disables inject runtime errors into parts of PGM." },
702# ifdef VBOX_STRICT
703 { "pgmassertcr3", 0, 0, NULL, 0, 0, pgmR3CmdAssertCR3, "", "Check the shadow CR3 mapping." },
704# ifdef VBOX_WITH_PAGE_SHARING
705 { "pgmcheckduppages", 0, 0, NULL, 0, 0, pgmR3CmdCheckDuplicatePages, "", "Check for duplicate pages in all running VMs." },
706 { "pgmsharedmodules", 0, 0, NULL, 0, 0, pgmR3CmdShowSharedModules, "", "Print shared modules info." },
707# endif
708# endif
709 { "pgmsyncalways", 0, 0, NULL, 0, 0, pgmR3CmdSyncAlways, "", "Toggle permanent CR3 syncing." },
710 { "pgmphystofile", 1, 2, &g_aPgmPhysToFileArgs[0], 2, 0, pgmR3CmdPhysToFile, "", "Save the physical memory to file." },
711};
712#endif
713
714#ifdef VBOX_WITH_PGM_NEM_MODE
715
716/**
717 * Interface that NEM uses to switch PGM into simplified memory managment mode.
718 *
719 * This call occurs before PGMR3Init.
720 *
721 * @param pVM The cross context VM structure.
722 */
723VMMR3_INT_DECL(void) PGMR3EnableNemMode(PVM pVM)
724{
725 AssertFatal(!PDMCritSectIsInitialized(&pVM->pgm.s.CritSectX));
726 pVM->pgm.s.fNemMode = true;
727}
728
729
730/**
731 * Checks whether the simplificed memory management mode for NEM is enabled.
732 *
733 * @returns true if enabled, false if not.
734 * @param pVM The cross context VM structure.
735 */
736VMMR3_INT_DECL(bool) PGMR3IsNemModeEnabled(PVM pVM)
737{
738 return pVM->pgm.s.fNemMode;
739}
740
741#endif /* VBOX_WITH_PGM_NEM_MODE */
742
743/**
744 * Initiates the paging of VM.
745 *
746 * @returns VBox status code.
747 * @param pVM The cross context VM structure.
748 */
749VMMR3DECL(int) PGMR3Init(PVM pVM)
750{
751 LogFlow(("PGMR3Init:\n"));
752 PCFGMNODE pCfgPGM = CFGMR3GetChild(CFGMR3GetRoot(pVM), "/PGM");
753 int rc;
754
755 /*
756 * Assert alignment and sizes.
757 */
758 AssertCompile(sizeof(pVM->pgm.s) <= sizeof(pVM->pgm.padding));
759 AssertCompile(sizeof(pVM->apCpusR3[0]->pgm.s) <= sizeof(pVM->apCpusR3[0]->pgm.padding));
760 AssertCompileMemberAlignment(PGM, CritSectX, sizeof(uintptr_t));
761
762 /*
763 * If we're in driveless mode we have to use the simplified memory mode.
764 */
765 bool const fDriverless = SUPR3IsDriverless();
766 if (fDriverless)
767 {
768#ifdef VBOX_WITH_PGM_NEM_MODE
769 if (!pVM->pgm.s.fNemMode)
770 pVM->pgm.s.fNemMode = true;
771#else
772 return VMR3SetError(pVM->pUVM, VERR_SUP_DRIVERLESS, RT_SRC_POS,
773 "Driverless requires that VBox is built with VBOX_WITH_PGM_NEM_MODE defined");
774#endif
775 }
776
777 /*
778 * Init the structure.
779 */
780 /*pVM->pgm.s.fRestoreRomPagesAtReset = false;*/
781
782 for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.aHandyPages); i++)
783 {
784 pVM->pgm.s.aHandyPages[i].HCPhysGCPhys = NIL_GMMPAGEDESC_PHYS;
785 pVM->pgm.s.aHandyPages[i].fZeroed = false;
786 pVM->pgm.s.aHandyPages[i].idPage = NIL_GMM_PAGEID;
787 pVM->pgm.s.aHandyPages[i].idSharedPage = NIL_GMM_PAGEID;
788 }
789
790 for (unsigned i = 0; i < RT_ELEMENTS(pVM->pgm.s.aLargeHandyPage); i++)
791 {
792 pVM->pgm.s.aLargeHandyPage[i].HCPhysGCPhys = NIL_GMMPAGEDESC_PHYS;
793 pVM->pgm.s.aLargeHandyPage[i].fZeroed = false;
794 pVM->pgm.s.aLargeHandyPage[i].idPage = NIL_GMM_PAGEID;
795 pVM->pgm.s.aLargeHandyPage[i].idSharedPage = NIL_GMM_PAGEID;
796 }
797
798 /* Init the per-CPU part. */
799 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
800 {
801 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
802 PPGMCPU pPGM = &pVCpu->pgm.s;
803
804 pPGM->enmShadowMode = PGMMODE_INVALID;
805 pPGM->enmGuestMode = PGMMODE_INVALID;
806 pPGM->enmGuestSlatMode = PGMSLAT_INVALID;
807 pPGM->idxGuestModeData = UINT8_MAX;
808 pPGM->idxShadowModeData = UINT8_MAX;
809 pPGM->idxBothModeData = UINT8_MAX;
810
811 pPGM->GCPhysCR3 = NIL_RTGCPHYS;
812 pPGM->GCPhysNstGstCR3 = NIL_RTGCPHYS;
813
814 pPGM->pGst32BitPdR3 = NULL;
815 pPGM->pGstPaePdptR3 = NULL;
816 pPGM->pGstAmd64Pml4R3 = NULL;
817 pPGM->pGst32BitPdR0 = NIL_RTR0PTR;
818 pPGM->pGstPaePdptR0 = NIL_RTR0PTR;
819 pPGM->pGstAmd64Pml4R0 = NIL_RTR0PTR;
820#ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
821 pPGM->pGstEptPml4R3 = NULL;
822 pPGM->pGstEptPml4R0 = NIL_RTR0PTR;
823 pPGM->uEptPtr = 0;
824#endif
825 for (unsigned i = 0; i < RT_ELEMENTS(pVCpu->pgm.s.apGstPaePDsR3); i++)
826 {
827 pPGM->apGstPaePDsR3[i] = NULL;
828 pPGM->apGstPaePDsR0[i] = NIL_RTR0PTR;
829 pPGM->aGCPhysGstPaePDs[i] = NIL_RTGCPHYS;
830 pPGM->aGCPhysGstPaePDsMonitored[i] = NIL_RTGCPHYS;
831 }
832
833 pPGM->fA20Enabled = true;
834 pPGM->GCPhysA20Mask = ~((RTGCPHYS)!pPGM->fA20Enabled << 20);
835 }
836
837 pVM->pgm.s.enmHostMode = SUPPAGINGMODE_INVALID;
838 pVM->pgm.s.GCPhys4MBPSEMask = RT_BIT_64(32) - 1; /* default; checked later */
839
840 rc = CFGMR3QueryBoolDef(CFGMR3GetRoot(pVM), "RamPreAlloc", &pVM->pgm.s.fRamPreAlloc,
841#ifdef VBOX_WITH_PREALLOC_RAM_BY_DEFAULT
842 true
843#else
844 false
845#endif
846 );
847 AssertLogRelRCReturn(rc, rc);
848
849#if HC_ARCH_BITS == 32
850# ifdef RT_OS_DARWIN
851 rc = CFGMR3QueryU32Def(pCfgPGM, "MaxRing3Chunks", &pVM->pgm.s.ChunkR3Map.cMax, _1G / GMM_CHUNK_SIZE * 3);
852# else
853 rc = CFGMR3QueryU32Def(pCfgPGM, "MaxRing3Chunks", &pVM->pgm.s.ChunkR3Map.cMax, _1G / GMM_CHUNK_SIZE);
854# endif
855#else
856 rc = CFGMR3QueryU32Def(pCfgPGM, "MaxRing3Chunks", &pVM->pgm.s.ChunkR3Map.cMax, UINT32_MAX);
857#endif
858 AssertLogRelRCReturn(rc, rc);
859 for (uint32_t i = 0; i < RT_ELEMENTS(pVM->pgm.s.ChunkR3Map.Tlb.aEntries); i++)
860 pVM->pgm.s.ChunkR3Map.Tlb.aEntries[i].idChunk = NIL_GMM_CHUNKID;
861
862 /*
863 * Get the configured RAM size - to estimate saved state size.
864 */
865 uint64_t cbRam;
866 rc = CFGMR3QueryU64(CFGMR3GetRoot(pVM), "RamSize", &cbRam);
867 if (rc == VERR_CFGM_VALUE_NOT_FOUND)
868 cbRam = 0;
869 else if (RT_SUCCESS(rc))
870 {
871 if (cbRam < PAGE_SIZE)
872 cbRam = 0;
873 cbRam = RT_ALIGN_64(cbRam, PAGE_SIZE);
874 }
875 else
876 {
877 AssertMsgFailed(("Configuration error: Failed to query integer \"RamSize\", rc=%Rrc.\n", rc));
878 return rc;
879 }
880
881 /*
882 * Check for PCI pass-through and other configurables.
883 */
884 rc = CFGMR3QueryBoolDef(pCfgPGM, "PciPassThrough", &pVM->pgm.s.fPciPassthrough, false);
885 AssertMsgRCReturn(rc, ("Configuration error: Failed to query integer \"PciPassThrough\", rc=%Rrc.\n", rc), rc);
886 AssertLogRelReturn(!pVM->pgm.s.fPciPassthrough || pVM->pgm.s.fRamPreAlloc, VERR_INVALID_PARAMETER);
887
888 rc = CFGMR3QueryBoolDef(CFGMR3GetRoot(pVM), "PageFusionAllowed", &pVM->pgm.s.fPageFusionAllowed, false);
889 AssertLogRelRCReturn(rc, rc);
890
891 /** @cfgm{/PGM/ZeroRamPagesOnReset, boolean, true}
892 * Whether to clear RAM pages on (hard) reset. */
893 rc = CFGMR3QueryBoolDef(pCfgPGM, "ZeroRamPagesOnReset", &pVM->pgm.s.fZeroRamPagesOnReset, true);
894 AssertLogRelRCReturn(rc, rc);
895
896 /*
897 * Register callbacks, string formatters and the saved state data unit.
898 */
899#ifdef VBOX_STRICT
900 VMR3AtStateRegister(pVM->pUVM, pgmR3ResetNoMorePhysWritesFlag, NULL);
901#endif
902 PGMRegisterStringFormatTypes();
903
904 rc = pgmR3InitSavedState(pVM, cbRam);
905 if (RT_FAILURE(rc))
906 return rc;
907
908 /*
909 * Initialize the PGM critical section and flush the phys TLBs
910 */
911 rc = PDMR3CritSectInit(pVM, &pVM->pgm.s.CritSectX, RT_SRC_POS, "PGM");
912 AssertRCReturn(rc, rc);
913
914 PGMR3PhysChunkInvalidateTLB(pVM);
915 pgmPhysInvalidatePageMapTLB(pVM);
916
917 /*
918 * For the time being we sport a full set of handy pages in addition to the base
919 * memory to simplify things.
920 */
921 rc = MMR3ReserveHandyPages(pVM, RT_ELEMENTS(pVM->pgm.s.aHandyPages)); /** @todo this should be changed to PGM_HANDY_PAGES_MIN but this needs proper testing... */
922 AssertRCReturn(rc, rc);
923
924 /*
925 * Trees
926 */
927 rc = MMHyperAlloc(pVM, sizeof(PGMTREES), 0, MM_TAG_PGM, (void **)&pVM->pgm.s.pTreesR3);
928 if (RT_SUCCESS(rc))
929 pVM->pgm.s.pTreesR0 = MMHyperR3ToR0(pVM, pVM->pgm.s.pTreesR3);
930
931 /*
932 * Allocate the zero page.
933 */
934 if (RT_SUCCESS(rc))
935 {
936 rc = MMHyperAlloc(pVM, PAGE_SIZE, PAGE_SIZE, MM_TAG_PGM, &pVM->pgm.s.pvZeroPgR3);
937 if (RT_SUCCESS(rc))
938 {
939 pVM->pgm.s.pvZeroPgR0 = MMHyperR3ToR0(pVM, pVM->pgm.s.pvZeroPgR3);
940 pVM->pgm.s.HCPhysZeroPg = !fDriverless ? MMR3HyperHCVirt2HCPhys(pVM, pVM->pgm.s.pvZeroPgR3)
941 : _4G - PAGE_SIZE * 2 /* fake to avoid PGM_PAGE_INIT_ZERO assertion */;
942 AssertRelease(pVM->pgm.s.HCPhysZeroPg != NIL_RTHCPHYS);
943 }
944 }
945
946 /*
947 * Allocate the invalid MMIO page.
948 * (The invalid bits in HCPhysInvMmioPg are set later on init complete.)
949 */
950 if (RT_SUCCESS(rc))
951 {
952 rc = MMHyperAlloc(pVM, PAGE_SIZE, PAGE_SIZE, MM_TAG_PGM, &pVM->pgm.s.pvMmioPgR3);
953 if (RT_SUCCESS(rc))
954 {
955 ASMMemFill32(pVM->pgm.s.pvMmioPgR3, PAGE_SIZE, 0xfeedface);
956 pVM->pgm.s.HCPhysMmioPg = !fDriverless ? MMR3HyperHCVirt2HCPhys(pVM, pVM->pgm.s.pvMmioPgR3)
957 : _4G - PAGE_SIZE * 3 /* fake to avoid PGM_PAGE_INIT_ZERO assertion */;
958 AssertRelease(pVM->pgm.s.HCPhysMmioPg != NIL_RTHCPHYS);
959 pVM->pgm.s.HCPhysInvMmioPg = pVM->pgm.s.HCPhysMmioPg;
960 }
961 }
962
963 /*
964 * Register the physical access handler protecting ROMs.
965 */
966 if (RT_SUCCESS(rc))
967 /** @todo why isn't pgmPhysRomWriteHandler registered for ring-0? */
968 rc = PGMR3HandlerPhysicalTypeRegister(pVM, PGMPHYSHANDLERKIND_WRITE, false /*fKeepPgmLock*/,
969 pgmPhysRomWriteHandler,
970 NULL, NULL, "pgmPhysRomWritePfHandler",
971 NULL, NULL, "pgmPhysRomWritePfHandler",
972 "ROM write protection",
973 &pVM->pgm.s.hRomPhysHandlerType);
974
975 /*
976 * Register the physical access handler doing dirty MMIO2 tracing.
977 */
978 if (RT_SUCCESS(rc))
979 rc = PGMR3HandlerPhysicalTypeRegister(pVM, PGMPHYSHANDLERKIND_WRITE, true /*fKeepPgmLock*/,
980 pgmPhysMmio2WriteHandler,
981 NULL, "pgmPhysMmio2WriteHandler", "pgmPhysMmio2WritePfHandler",
982 NULL, "pgmPhysMmio2WriteHandler", "pgmPhysMmio2WritePfHandler",
983 "MMIO2 dirty page tracing",
984 &pVM->pgm.s.hMmio2DirtyPhysHandlerType);
985
986 /*
987 * Init the paging.
988 */
989 if (RT_SUCCESS(rc))
990 rc = pgmR3InitPaging(pVM);
991
992 /*
993 * Init the page pool.
994 */
995 if (RT_SUCCESS(rc))
996 rc = pgmR3PoolInit(pVM);
997
998 if (RT_SUCCESS(rc))
999 {
1000 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1001 {
1002 PVMCPU pVCpu = pVM->apCpusR3[i];
1003 rc = PGMHCChangeMode(pVM, pVCpu, PGMMODE_REAL);
1004 if (RT_FAILURE(rc))
1005 break;
1006 }
1007 }
1008
1009 if (RT_SUCCESS(rc))
1010 {
1011 /*
1012 * Info & statistics
1013 */
1014 DBGFR3InfoRegisterInternalEx(pVM, "mode",
1015 "Shows the current paging mode. "
1016 "Recognizes 'all', 'guest', 'shadow' and 'host' as arguments, defaulting to 'all' if nothing is given.",
1017 pgmR3InfoMode,
1018 DBGFINFO_FLAGS_ALL_EMTS);
1019 DBGFR3InfoRegisterInternal(pVM, "pgmcr3",
1020 "Dumps all the entries in the top level paging table. No arguments.",
1021 pgmR3InfoCr3);
1022 DBGFR3InfoRegisterInternal(pVM, "phys",
1023 "Dumps all the physical address ranges. Pass 'verbose' to get more details.",
1024 pgmR3PhysInfo);
1025 DBGFR3InfoRegisterInternal(pVM, "handlers",
1026 "Dumps physical, virtual and hyper virtual handlers. "
1027 "Pass 'phys', 'virt', 'hyper' as argument if only one kind is wanted."
1028 "Add 'nost' if the statistics are unwanted, use together with 'all' or explicit selection.",
1029 pgmR3InfoHandlers);
1030
1031 pgmR3InitStats(pVM);
1032
1033#ifdef VBOX_WITH_DEBUGGER
1034 /*
1035 * Debugger commands.
1036 */
1037 static bool s_fRegisteredCmds = false;
1038 if (!s_fRegisteredCmds)
1039 {
1040 int rc2 = DBGCRegisterCommands(&g_aCmds[0], RT_ELEMENTS(g_aCmds));
1041 if (RT_SUCCESS(rc2))
1042 s_fRegisteredCmds = true;
1043 }
1044#endif
1045
1046#ifdef RT_OS_LINUX
1047 /*
1048 * Log the /proc/sys/vm/max_map_count value on linux as that is
1049 * frequently giving us grief when too low.
1050 */
1051 int64_t const cGuessNeeded = MMR3PhysGetRamSize(pVM) / _2M + 16384 /*guesstimate*/;
1052 int64_t cMaxMapCount = 0;
1053 int rc2 = RTLinuxSysFsReadIntFile(10, &cMaxMapCount, "/proc/sys/vm/max_map_count");
1054 LogRel(("PGM: /proc/sys/vm/max_map_count = %RI64 (rc2=%Rrc); cGuessNeeded=%RI64\n", cMaxMapCount, rc2, cGuessNeeded));
1055 if (RT_SUCCESS(rc2) && cMaxMapCount < cGuessNeeded)
1056 LogRel(("PGM: WARNING!!\n"
1057 "PGM: WARNING!! Please increase /proc/sys/vm/max_map_count to at least %RI64 (or reduce the amount of RAM assigned to the VM)!\n"
1058 "PGM: WARNING!!\n", cMaxMapCount));
1059
1060#endif
1061
1062 return VINF_SUCCESS;
1063 }
1064
1065 /* Almost no cleanup necessary, MM frees all memory. */
1066 PDMR3CritSectDelete(pVM, &pVM->pgm.s.CritSectX);
1067
1068 return rc;
1069}
1070
1071
1072/**
1073 * Init paging.
1074 *
1075 * Since we need to check what mode the host is operating in before we can choose
1076 * the right paging functions for the host we have to delay this until R0 has
1077 * been initialized.
1078 *
1079 * @returns VBox status code.
1080 * @param pVM The cross context VM structure.
1081 */
1082static int pgmR3InitPaging(PVM pVM)
1083{
1084 /*
1085 * Force a recalculation of modes and switcher so everyone gets notified.
1086 */
1087 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1088 {
1089 PVMCPU pVCpu = pVM->apCpusR3[i];
1090
1091 pVCpu->pgm.s.enmShadowMode = PGMMODE_INVALID;
1092 pVCpu->pgm.s.enmGuestMode = PGMMODE_INVALID;
1093 pVCpu->pgm.s.enmGuestSlatMode = PGMSLAT_INVALID;
1094 pVCpu->pgm.s.idxGuestModeData = UINT8_MAX;
1095 pVCpu->pgm.s.idxShadowModeData = UINT8_MAX;
1096 pVCpu->pgm.s.idxBothModeData = UINT8_MAX;
1097 }
1098
1099 pVM->pgm.s.enmHostMode = SUPPAGINGMODE_INVALID;
1100
1101 /*
1102 * Initialize paging workers and mode from current host mode
1103 * and the guest running in real mode.
1104 */
1105 pVM->pgm.s.enmHostMode = SUPR3GetPagingMode();
1106 switch (pVM->pgm.s.enmHostMode)
1107 {
1108 case SUPPAGINGMODE_32_BIT:
1109 case SUPPAGINGMODE_32_BIT_GLOBAL:
1110 case SUPPAGINGMODE_PAE:
1111 case SUPPAGINGMODE_PAE_GLOBAL:
1112 case SUPPAGINGMODE_PAE_NX:
1113 case SUPPAGINGMODE_PAE_GLOBAL_NX:
1114 break;
1115
1116 case SUPPAGINGMODE_AMD64:
1117 case SUPPAGINGMODE_AMD64_GLOBAL:
1118 case SUPPAGINGMODE_AMD64_NX:
1119 case SUPPAGINGMODE_AMD64_GLOBAL_NX:
1120 if (ARCH_BITS != 64)
1121 {
1122 AssertMsgFailed(("Host mode %d (64-bit) is not supported by non-64bit builds\n", pVM->pgm.s.enmHostMode));
1123 LogRel(("PGM: Host mode %d (64-bit) is not supported by non-64bit builds\n", pVM->pgm.s.enmHostMode));
1124 return VERR_PGM_UNSUPPORTED_HOST_PAGING_MODE;
1125 }
1126 break;
1127 default:
1128 AssertMsgFailed(("Host mode %d is not supported\n", pVM->pgm.s.enmHostMode));
1129 return VERR_PGM_UNSUPPORTED_HOST_PAGING_MODE;
1130 }
1131
1132 LogFlow(("pgmR3InitPaging: returns successfully\n"));
1133#if HC_ARCH_BITS == 64 && 0
1134 LogRel(("PGM: HCPhysInterPD=%RHp HCPhysInterPaePDPT=%RHp HCPhysInterPaePML4=%RHp\n",
1135 pVM->pgm.s.HCPhysInterPD, pVM->pgm.s.HCPhysInterPaePDPT, pVM->pgm.s.HCPhysInterPaePML4));
1136 LogRel(("PGM: apInterPTs={%RHp,%RHp} apInterPaePTs={%RHp,%RHp} apInterPaePDs={%RHp,%RHp,%RHp,%RHp} pInterPaePDPT64=%RHp\n",
1137 MMPage2Phys(pVM, pVM->pgm.s.apInterPTs[0]), MMPage2Phys(pVM, pVM->pgm.s.apInterPTs[1]),
1138 MMPage2Phys(pVM, pVM->pgm.s.apInterPaePTs[0]), MMPage2Phys(pVM, pVM->pgm.s.apInterPaePTs[1]),
1139 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]),
1140 MMPage2Phys(pVM, pVM->pgm.s.pInterPaePDPT64)));
1141#endif
1142
1143 /*
1144 * Log the host paging mode. It may come in handy.
1145 */
1146 const char *pszHostMode;
1147 switch (pVM->pgm.s.enmHostMode)
1148 {
1149 case SUPPAGINGMODE_32_BIT: pszHostMode = "32-bit"; break;
1150 case SUPPAGINGMODE_32_BIT_GLOBAL: pszHostMode = "32-bit+PGE"; break;
1151 case SUPPAGINGMODE_PAE: pszHostMode = "PAE"; break;
1152 case SUPPAGINGMODE_PAE_GLOBAL: pszHostMode = "PAE+PGE"; break;
1153 case SUPPAGINGMODE_PAE_NX: pszHostMode = "PAE+NXE"; break;
1154 case SUPPAGINGMODE_PAE_GLOBAL_NX: pszHostMode = "PAE+PGE+NXE"; break;
1155 case SUPPAGINGMODE_AMD64: pszHostMode = "AMD64"; break;
1156 case SUPPAGINGMODE_AMD64_GLOBAL: pszHostMode = "AMD64+PGE"; break;
1157 case SUPPAGINGMODE_AMD64_NX: pszHostMode = "AMD64+NX"; break;
1158 case SUPPAGINGMODE_AMD64_GLOBAL_NX: pszHostMode = "AMD64+PGE+NX"; break;
1159 default: pszHostMode = "???"; break;
1160 }
1161 LogRel(("PGM: Host paging mode: %s\n", pszHostMode));
1162
1163 return VINF_SUCCESS;
1164}
1165
1166
1167/**
1168 * Init statistics
1169 * @returns VBox status code.
1170 */
1171static int pgmR3InitStats(PVM pVM)
1172{
1173 PPGM pPGM = &pVM->pgm.s;
1174 int rc;
1175
1176 /*
1177 * Release statistics.
1178 */
1179 /* Common - misc variables */
1180 STAM_REL_REG(pVM, &pPGM->cAllPages, STAMTYPE_U32, "/PGM/Page/cAllPages", STAMUNIT_COUNT, "The total number of pages.");
1181 STAM_REL_REG(pVM, &pPGM->cPrivatePages, STAMTYPE_U32, "/PGM/Page/cPrivatePages", STAMUNIT_COUNT, "The number of private pages.");
1182 STAM_REL_REG(pVM, &pPGM->cSharedPages, STAMTYPE_U32, "/PGM/Page/cSharedPages", STAMUNIT_COUNT, "The number of shared pages.");
1183 STAM_REL_REG(pVM, &pPGM->cReusedSharedPages, STAMTYPE_U32, "/PGM/Page/cReusedSharedPages", STAMUNIT_COUNT, "The number of reused shared pages.");
1184 STAM_REL_REG(pVM, &pPGM->cZeroPages, STAMTYPE_U32, "/PGM/Page/cZeroPages", STAMUNIT_COUNT, "The number of zero backed pages.");
1185 STAM_REL_REG(pVM, &pPGM->cPureMmioPages, STAMTYPE_U32, "/PGM/Page/cPureMmioPages", STAMUNIT_COUNT, "The number of pure MMIO pages.");
1186 STAM_REL_REG(pVM, &pPGM->cMonitoredPages, STAMTYPE_U32, "/PGM/Page/cMonitoredPages", STAMUNIT_COUNT, "The number of write monitored pages.");
1187 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.");
1188 STAM_REL_REG(pVM, &pPGM->cWriteLockedPages, STAMTYPE_U32, "/PGM/Page/cWriteLockedPages", STAMUNIT_COUNT, "The number of write(/read) locked pages.");
1189 STAM_REL_REG(pVM, &pPGM->cReadLockedPages, STAMTYPE_U32, "/PGM/Page/cReadLockedPages", STAMUNIT_COUNT, "The number of read (only) locked pages.");
1190 STAM_REL_REG(pVM, &pPGM->cBalloonedPages, STAMTYPE_U32, "/PGM/Page/cBalloonedPages", STAMUNIT_COUNT, "The number of ballooned pages.");
1191 STAM_REL_REG(pVM, &pPGM->cHandyPages, STAMTYPE_U32, "/PGM/Page/cHandyPages", STAMUNIT_COUNT, "The number of handy pages (not included in cAllPages).");
1192 STAM_REL_REG(pVM, &pPGM->cLargePages, STAMTYPE_U32, "/PGM/Page/cLargePages", STAMUNIT_COUNT, "The number of large pages allocated (includes disabled).");
1193 STAM_REL_REG(pVM, &pPGM->cLargePagesDisabled, STAMTYPE_U32, "/PGM/Page/cLargePagesDisabled", STAMUNIT_COUNT, "The number of disabled large pages.");
1194 STAM_REL_REG(pVM, &pPGM->ChunkR3Map.c, STAMTYPE_U32, "/PGM/ChunkR3Map/c", STAMUNIT_COUNT, "Number of mapped chunks.");
1195 STAM_REL_REG(pVM, &pPGM->ChunkR3Map.cMax, STAMTYPE_U32, "/PGM/ChunkR3Map/cMax", STAMUNIT_COUNT, "Maximum number of mapped chunks.");
1196 STAM_REL_REG(pVM, &pPGM->cMappedChunks, STAMTYPE_U32, "/PGM/ChunkR3Map/Mapped", STAMUNIT_COUNT, "Number of times we mapped a chunk.");
1197 STAM_REL_REG(pVM, &pPGM->cUnmappedChunks, STAMTYPE_U32, "/PGM/ChunkR3Map/Unmapped", STAMUNIT_COUNT, "Number of times we unmapped a chunk.");
1198
1199 STAM_REL_REG(pVM, &pPGM->StatLargePageReused, STAMTYPE_COUNTER, "/PGM/LargePage/Reused", STAMUNIT_OCCURENCES, "The number of times we've reused a large page.");
1200 STAM_REL_REG(pVM, &pPGM->StatLargePageRefused, STAMTYPE_COUNTER, "/PGM/LargePage/Refused", STAMUNIT_OCCURENCES, "The number of times we couldn't use a large page.");
1201 STAM_REL_REG(pVM, &pPGM->StatLargePageRecheck, STAMTYPE_COUNTER, "/PGM/LargePage/Recheck", STAMUNIT_OCCURENCES, "The number of times we've rechecked a disabled large page.");
1202
1203 STAM_REL_REG(pVM, &pPGM->StatShModCheck, STAMTYPE_PROFILE, "/PGM/ShMod/Check", STAMUNIT_TICKS_PER_CALL, "Profiles the shared module checking.");
1204 STAM_REL_REG(pVM, &pPGM->StatMmio2QueryAndResetDirtyBitmap, STAMTYPE_PROFILE, "/PGM/Mmio2QueryAndResetDirtyBitmap", STAMUNIT_TICKS_PER_CALL, "Profiles calls to PGMR3PhysMmio2QueryAndResetDirtyBitmap (sans locking).");
1205
1206 /* Live save */
1207 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.fActive, STAMTYPE_U8, "/PGM/LiveSave/fActive", STAMUNIT_COUNT, "Active or not.");
1208 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).");
1209 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.cDirtyPagesLong, STAMTYPE_U32, "/PGM/LiveSave/cDirtyPagesLong", STAMUNIT_COUNT, "Longer term dirty page average.");
1210 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.cDirtyPagesShort, STAMTYPE_U32, "/PGM/LiveSave/cDirtyPagesShort", STAMUNIT_COUNT, "Short term dirty page average.");
1211 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.cPagesPerSecond, STAMTYPE_U32, "/PGM/LiveSave/cPagesPerSecond", STAMUNIT_COUNT, "Pages per second.");
1212 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.cSavedPages, STAMTYPE_U64, "/PGM/LiveSave/cSavedPages", STAMUNIT_COUNT, "The total number of saved pages.");
1213 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Ram.cReadyPages, STAMTYPE_U32, "/PGM/LiveSave/Ram/cReadPages", STAMUNIT_COUNT, "RAM: Ready pages.");
1214 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Ram.cDirtyPages, STAMTYPE_U32, "/PGM/LiveSave/Ram/cDirtyPages", STAMUNIT_COUNT, "RAM: Dirty pages.");
1215 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Ram.cZeroPages, STAMTYPE_U32, "/PGM/LiveSave/Ram/cZeroPages", STAMUNIT_COUNT, "RAM: Ready zero pages.");
1216 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Ram.cMonitoredPages, STAMTYPE_U32, "/PGM/LiveSave/Ram/cMonitoredPages", STAMUNIT_COUNT, "RAM: Write monitored pages.");
1217 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Rom.cReadyPages, STAMTYPE_U32, "/PGM/LiveSave/Rom/cReadPages", STAMUNIT_COUNT, "ROM: Ready pages.");
1218 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Rom.cDirtyPages, STAMTYPE_U32, "/PGM/LiveSave/Rom/cDirtyPages", STAMUNIT_COUNT, "ROM: Dirty pages.");
1219 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Rom.cZeroPages, STAMTYPE_U32, "/PGM/LiveSave/Rom/cZeroPages", STAMUNIT_COUNT, "ROM: Ready zero pages.");
1220 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Rom.cMonitoredPages, STAMTYPE_U32, "/PGM/LiveSave/Rom/cMonitoredPages", STAMUNIT_COUNT, "ROM: Write monitored pages.");
1221 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Mmio2.cReadyPages, STAMTYPE_U32, "/PGM/LiveSave/Mmio2/cReadPages", STAMUNIT_COUNT, "MMIO2: Ready pages.");
1222 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Mmio2.cDirtyPages, STAMTYPE_U32, "/PGM/LiveSave/Mmio2/cDirtyPages", STAMUNIT_COUNT, "MMIO2: Dirty pages.");
1223 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Mmio2.cZeroPages, STAMTYPE_U32, "/PGM/LiveSave/Mmio2/cZeroPages", STAMUNIT_COUNT, "MMIO2: Ready zero pages.");
1224 STAM_REL_REG_USED(pVM, &pPGM->LiveSave.Mmio2.cMonitoredPages,STAMTYPE_U32, "/PGM/LiveSave/Mmio2/cMonitoredPages",STAMUNIT_COUNT, "MMIO2: Write monitored pages.");
1225
1226#define PGM_REG_COUNTER(a, b, c) \
1227 rc = STAMR3RegisterF(pVM, a, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, c, b); \
1228 AssertRC(rc);
1229
1230#define PGM_REG_COUNTER_BYTES(a, b, c) \
1231 rc = STAMR3RegisterF(pVM, a, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES, c, b); \
1232 AssertRC(rc);
1233
1234#define PGM_REG_PROFILE(a, b, c) \
1235 rc = STAMR3RegisterF(pVM, a, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, c, b); \
1236 AssertRC(rc);
1237#define PGM_REG_PROFILE_NS(a, b, c) \
1238 rc = STAMR3RegisterF(pVM, a, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_NS_PER_CALL, c, b); \
1239 AssertRC(rc);
1240
1241#ifdef VBOX_WITH_STATISTICS
1242 PGMSTATS *pStats = &pPGM->Stats;
1243#endif
1244
1245 PGM_REG_PROFILE_NS(&pPGM->StatLargePageAlloc, "/PGM/LargePage/Alloc", "Time spent by the host OS for large page allocation.");
1246 PGM_REG_COUNTER(&pPGM->StatLargePageAllocFailed, "/PGM/LargePage/AllocFailed", "Number of allocation failures.");
1247 PGM_REG_COUNTER(&pPGM->StatLargePageOverflow, "/PGM/LargePage/Overflow", "The number of times allocating a large page took too long.");
1248 PGM_REG_COUNTER(&pPGM->StatLargePageTlbFlush, "/PGM/LargePage/TlbFlush", "The number of times a full VCPU TLB flush was required after a large allocation.");
1249 PGM_REG_COUNTER(&pPGM->StatLargePageZeroEvict, "/PGM/LargePage/ZeroEvict", "The number of zero page mappings we had to evict when allocating a large page.");
1250#ifdef VBOX_WITH_STATISTICS
1251 PGM_REG_PROFILE(&pStats->StatLargePageAlloc2, "/PGM/LargePage/Alloc2", "Time spent allocating large pages.");
1252 PGM_REG_PROFILE(&pStats->StatLargePageSetup, "/PGM/LargePage/Setup", "Time spent setting up the newly allocated large pages.");
1253 PGM_REG_PROFILE(&pStats->StatR3IsValidLargePage, "/PGM/LargePage/IsValidR3", "pgmPhysIsValidLargePage profiling - R3.");
1254 PGM_REG_PROFILE(&pStats->StatRZIsValidLargePage, "/PGM/LargePage/IsValidRZ", "pgmPhysIsValidLargePage profiling - RZ.");
1255
1256 PGM_REG_COUNTER(&pStats->StatR3DetectedConflicts, "/PGM/R3/DetectedConflicts", "The number of times PGMR3CheckMappingConflicts() detected a conflict.");
1257 PGM_REG_PROFILE(&pStats->StatR3ResolveConflict, "/PGM/R3/ResolveConflict", "pgmR3SyncPTResolveConflict() profiling (includes the entire relocation).");
1258 PGM_REG_COUNTER(&pStats->StatR3PhysRead, "/PGM/R3/Phys/Read", "The number of times PGMPhysRead was called.");
1259 PGM_REG_COUNTER_BYTES(&pStats->StatR3PhysReadBytes, "/PGM/R3/Phys/Read/Bytes", "The number of bytes read by PGMPhysRead.");
1260 PGM_REG_COUNTER(&pStats->StatR3PhysWrite, "/PGM/R3/Phys/Write", "The number of times PGMPhysWrite was called.");
1261 PGM_REG_COUNTER_BYTES(&pStats->StatR3PhysWriteBytes, "/PGM/R3/Phys/Write/Bytes", "The number of bytes written by PGMPhysWrite.");
1262 PGM_REG_COUNTER(&pStats->StatR3PhysSimpleRead, "/PGM/R3/Phys/Simple/Read", "The number of times PGMPhysSimpleReadGCPtr was called.");
1263 PGM_REG_COUNTER_BYTES(&pStats->StatR3PhysSimpleReadBytes, "/PGM/R3/Phys/Simple/Read/Bytes", "The number of bytes read by PGMPhysSimpleReadGCPtr.");
1264 PGM_REG_COUNTER(&pStats->StatR3PhysSimpleWrite, "/PGM/R3/Phys/Simple/Write", "The number of times PGMPhysSimpleWriteGCPtr was called.");
1265 PGM_REG_COUNTER_BYTES(&pStats->StatR3PhysSimpleWriteBytes, "/PGM/R3/Phys/Simple/Write/Bytes", "The number of bytes written by PGMPhysSimpleWriteGCPtr.");
1266
1267 PGM_REG_COUNTER(&pStats->StatRZChunkR3MapTlbHits, "/PGM/ChunkR3Map/TlbHitsRZ", "TLB hits.");
1268 PGM_REG_COUNTER(&pStats->StatRZChunkR3MapTlbMisses, "/PGM/ChunkR3Map/TlbMissesRZ", "TLB misses.");
1269 PGM_REG_PROFILE(&pStats->StatChunkAging, "/PGM/ChunkR3Map/Map/Aging", "Chunk aging profiling.");
1270 PGM_REG_PROFILE(&pStats->StatChunkFindCandidate, "/PGM/ChunkR3Map/Map/Find", "Chunk unmap find profiling.");
1271 PGM_REG_PROFILE(&pStats->StatChunkUnmap, "/PGM/ChunkR3Map/Map/Unmap", "Chunk unmap of address space profiling.");
1272 PGM_REG_PROFILE(&pStats->StatChunkMap, "/PGM/ChunkR3Map/Map/Map", "Chunk map of address space profiling.");
1273
1274 PGM_REG_COUNTER(&pStats->StatRZPageMapTlbHits, "/PGM/RZ/Page/MapTlbHits", "TLB hits.");
1275 PGM_REG_COUNTER(&pStats->StatRZPageMapTlbMisses, "/PGM/RZ/Page/MapTlbMisses", "TLB misses.");
1276 PGM_REG_COUNTER(&pStats->StatR3ChunkR3MapTlbHits, "/PGM/ChunkR3Map/TlbHitsR3", "TLB hits.");
1277 PGM_REG_COUNTER(&pStats->StatR3ChunkR3MapTlbMisses, "/PGM/ChunkR3Map/TlbMissesR3", "TLB misses.");
1278 PGM_REG_COUNTER(&pStats->StatR3PageMapTlbHits, "/PGM/R3/Page/MapTlbHits", "TLB hits.");
1279 PGM_REG_COUNTER(&pStats->StatR3PageMapTlbMisses, "/PGM/R3/Page/MapTlbMisses", "TLB misses.");
1280 PGM_REG_COUNTER(&pStats->StatPageMapTlbFlushes, "/PGM/R3/Page/MapTlbFlushes", "TLB flushes (all contexts).");
1281 PGM_REG_COUNTER(&pStats->StatPageMapTlbFlushEntry, "/PGM/R3/Page/MapTlbFlushEntry", "TLB entry flushes (all contexts).");
1282
1283 PGM_REG_COUNTER(&pStats->StatRZRamRangeTlbHits, "/PGM/RZ/RamRange/TlbHits", "TLB hits.");
1284 PGM_REG_COUNTER(&pStats->StatRZRamRangeTlbMisses, "/PGM/RZ/RamRange/TlbMisses", "TLB misses.");
1285 PGM_REG_COUNTER(&pStats->StatR3RamRangeTlbHits, "/PGM/R3/RamRange/TlbHits", "TLB hits.");
1286 PGM_REG_COUNTER(&pStats->StatR3RamRangeTlbMisses, "/PGM/R3/RamRange/TlbMisses", "TLB misses.");
1287
1288 PGM_REG_COUNTER(&pStats->StatRZPhysHandlerReset, "/PGM/RZ/PhysHandlerReset", "The number of times PGMHandlerPhysicalReset is called.");
1289 PGM_REG_COUNTER(&pStats->StatR3PhysHandlerReset, "/PGM/R3/PhysHandlerReset", "The number of times PGMHandlerPhysicalReset is called.");
1290 PGM_REG_COUNTER(&pStats->StatRZPhysHandlerLookupHits, "/PGM/RZ/PhysHandlerLookupHits", "The number of cache hits when looking up physical handlers.");
1291 PGM_REG_COUNTER(&pStats->StatR3PhysHandlerLookupHits, "/PGM/R3/PhysHandlerLookupHits", "The number of cache hits when looking up physical handlers.");
1292 PGM_REG_COUNTER(&pStats->StatRZPhysHandlerLookupMisses, "/PGM/RZ/PhysHandlerLookupMisses", "The number of cache misses when looking up physical handlers.");
1293 PGM_REG_COUNTER(&pStats->StatR3PhysHandlerLookupMisses, "/PGM/R3/PhysHandlerLookupMisses", "The number of cache misses when looking up physical handlers.");
1294
1295 PGM_REG_COUNTER(&pStats->StatRZPageReplaceShared, "/PGM/RZ/Page/ReplacedShared", "Times a shared page was replaced.");
1296 PGM_REG_COUNTER(&pStats->StatRZPageReplaceZero, "/PGM/RZ/Page/ReplacedZero", "Times the zero page was replaced.");
1297/// @todo PGM_REG_COUNTER(&pStats->StatRZPageHandyAllocs, "/PGM/RZ/Page/HandyAllocs", "Number of times we've allocated more handy pages.");
1298 PGM_REG_COUNTER(&pStats->StatR3PageReplaceShared, "/PGM/R3/Page/ReplacedShared", "Times a shared page was replaced.");
1299 PGM_REG_COUNTER(&pStats->StatR3PageReplaceZero, "/PGM/R3/Page/ReplacedZero", "Times the zero page was replaced.");
1300/// @todo PGM_REG_COUNTER(&pStats->StatR3PageHandyAllocs, "/PGM/R3/Page/HandyAllocs", "Number of times we've allocated more handy pages.");
1301
1302 PGM_REG_COUNTER(&pStats->StatRZPhysRead, "/PGM/RZ/Phys/Read", "The number of times PGMPhysRead was called.");
1303 PGM_REG_COUNTER_BYTES(&pStats->StatRZPhysReadBytes, "/PGM/RZ/Phys/Read/Bytes", "The number of bytes read by PGMPhysRead.");
1304 PGM_REG_COUNTER(&pStats->StatRZPhysWrite, "/PGM/RZ/Phys/Write", "The number of times PGMPhysWrite was called.");
1305 PGM_REG_COUNTER_BYTES(&pStats->StatRZPhysWriteBytes, "/PGM/RZ/Phys/Write/Bytes", "The number of bytes written by PGMPhysWrite.");
1306 PGM_REG_COUNTER(&pStats->StatRZPhysSimpleRead, "/PGM/RZ/Phys/Simple/Read", "The number of times PGMPhysSimpleReadGCPtr was called.");
1307 PGM_REG_COUNTER_BYTES(&pStats->StatRZPhysSimpleReadBytes, "/PGM/RZ/Phys/Simple/Read/Bytes", "The number of bytes read by PGMPhysSimpleReadGCPtr.");
1308 PGM_REG_COUNTER(&pStats->StatRZPhysSimpleWrite, "/PGM/RZ/Phys/Simple/Write", "The number of times PGMPhysSimpleWriteGCPtr was called.");
1309 PGM_REG_COUNTER_BYTES(&pStats->StatRZPhysSimpleWriteBytes, "/PGM/RZ/Phys/Simple/Write/Bytes", "The number of bytes written by PGMPhysSimpleWriteGCPtr.");
1310
1311 /* GC only: */
1312 PGM_REG_COUNTER(&pStats->StatRCInvlPgConflict, "/PGM/RC/InvlPgConflict", "Number of times PGMInvalidatePage() detected a mapping conflict.");
1313 PGM_REG_COUNTER(&pStats->StatRCInvlPgSyncMonCR3, "/PGM/RC/InvlPgSyncMonitorCR3", "Number of times PGMInvalidatePage() ran into PGM_SYNC_MONITOR_CR3.");
1314
1315 PGM_REG_COUNTER(&pStats->StatRCPhysRead, "/PGM/RC/Phys/Read", "The number of times PGMPhysRead was called.");
1316 PGM_REG_COUNTER_BYTES(&pStats->StatRCPhysReadBytes, "/PGM/RC/Phys/Read/Bytes", "The number of bytes read by PGMPhysRead.");
1317 PGM_REG_COUNTER(&pStats->StatRCPhysWrite, "/PGM/RC/Phys/Write", "The number of times PGMPhysWrite was called.");
1318 PGM_REG_COUNTER_BYTES(&pStats->StatRCPhysWriteBytes, "/PGM/RC/Phys/Write/Bytes", "The number of bytes written by PGMPhysWrite.");
1319 PGM_REG_COUNTER(&pStats->StatRCPhysSimpleRead, "/PGM/RC/Phys/Simple/Read", "The number of times PGMPhysSimpleReadGCPtr was called.");
1320 PGM_REG_COUNTER_BYTES(&pStats->StatRCPhysSimpleReadBytes, "/PGM/RC/Phys/Simple/Read/Bytes", "The number of bytes read by PGMPhysSimpleReadGCPtr.");
1321 PGM_REG_COUNTER(&pStats->StatRCPhysSimpleWrite, "/PGM/RC/Phys/Simple/Write", "The number of times PGMPhysSimpleWriteGCPtr was called.");
1322 PGM_REG_COUNTER_BYTES(&pStats->StatRCPhysSimpleWriteBytes, "/PGM/RC/Phys/Simple/Write/Bytes", "The number of bytes written by PGMPhysSimpleWriteGCPtr.");
1323
1324 PGM_REG_COUNTER(&pStats->StatTrackVirgin, "/PGM/Track/Virgin", "The number of first time shadowings");
1325 PGM_REG_COUNTER(&pStats->StatTrackAliased, "/PGM/Track/Aliased", "The number of times switching to cRef2, i.e. the page is being shadowed by two PTs.");
1326 PGM_REG_COUNTER(&pStats->StatTrackAliasedMany, "/PGM/Track/AliasedMany", "The number of times we're tracking using cRef2.");
1327 PGM_REG_COUNTER(&pStats->StatTrackAliasedLots, "/PGM/Track/AliasedLots", "The number of times we're hitting pages which has overflowed cRef2");
1328 PGM_REG_COUNTER(&pStats->StatTrackOverflows, "/PGM/Track/Overflows", "The number of times the extent list grows too long.");
1329 PGM_REG_COUNTER(&pStats->StatTrackNoExtentsLeft, "/PGM/Track/NoExtentLeft", "The number of times the extent list was exhausted.");
1330 PGM_REG_PROFILE(&pStats->StatTrackDeref, "/PGM/Track/Deref", "Profiling of SyncPageWorkerTrackDeref (expensive).");
1331#endif
1332
1333#undef PGM_REG_COUNTER
1334#undef PGM_REG_PROFILE
1335#undef PGM_REG_PROFILE_NS
1336
1337 /*
1338 * Note! The layout below matches the member layout exactly!
1339 */
1340
1341 /*
1342 * Common - stats
1343 */
1344 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1345 {
1346 PPGMCPU pPgmCpu = &pVM->apCpusR3[idCpu]->pgm.s;
1347
1348#define PGM_REG_COUNTER(a, b, c) \
1349 rc = STAMR3RegisterF(pVM, a, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, c, b, idCpu); \
1350 AssertRC(rc);
1351#define PGM_REG_PROFILE(a, b, c) \
1352 rc = STAMR3RegisterF(pVM, a, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, c, b, idCpu); \
1353 AssertRC(rc);
1354
1355 PGM_REG_COUNTER(&pPgmCpu->cGuestModeChanges, "/PGM/CPU%u/cGuestModeChanges", "Number of guest mode changes.");
1356 PGM_REG_COUNTER(&pPgmCpu->cA20Changes, "/PGM/CPU%u/cA20Changes", "Number of A20 gate changes.");
1357
1358#ifdef VBOX_WITH_STATISTICS
1359 PGMCPUSTATS *pCpuStats = &pVM->apCpusR3[idCpu]->pgm.s.Stats;
1360
1361# if 0 /* rarely useful; leave for debugging. */
1362 for (unsigned j = 0; j < RT_ELEMENTS(pPgmCpu->StatSyncPtPD); j++)
1363 STAMR3RegisterF(pVM, &pCpuStats->StatSyncPtPD[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
1364 "The number of SyncPT per PD n.", "/PGM/CPU%u/PDSyncPT/%04X", i, j);
1365 for (unsigned j = 0; j < RT_ELEMENTS(pCpuStats->StatSyncPagePD); j++)
1366 STAMR3RegisterF(pVM, &pCpuStats->StatSyncPagePD[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
1367 "The number of SyncPage per PD n.", "/PGM/CPU%u/PDSyncPage/%04X", i, j);
1368# endif
1369 /* R0 only: */
1370 PGM_REG_PROFILE(&pCpuStats->StatR0NpMiscfg, "/PGM/CPU%u/R0/NpMiscfg", "PGMR0Trap0eHandlerNPMisconfig() profiling.");
1371 PGM_REG_COUNTER(&pCpuStats->StatR0NpMiscfgSyncPage, "/PGM/CPU%u/R0/NpMiscfgSyncPage", "SyncPage calls from PGMR0Trap0eHandlerNPMisconfig().");
1372
1373 /* RZ only: */
1374 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0e, "/PGM/CPU%u/RZ/Trap0e", "Profiling of the PGMTrap0eHandler() body.");
1375 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2Ballooned, "/PGM/CPU%u/RZ/Trap0e/Time2/Ballooned", "Profiling of the Trap0eHandler body when the cause is read access to a ballooned page.");
1376 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2CSAM, "/PGM/CPU%u/RZ/Trap0e/Time2/CSAM", "Profiling of the Trap0eHandler body when the cause is CSAM.");
1377 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2DirtyAndAccessed, "/PGM/CPU%u/RZ/Trap0e/Time2/DirtyAndAccessedBits", "Profiling of the Trap0eHandler body when the cause is dirty and/or accessed bit emulation.");
1378 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2GuestTrap, "/PGM/CPU%u/RZ/Trap0e/Time2/GuestTrap", "Profiling of the Trap0eHandler body when the cause is a guest trap.");
1379 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2HndPhys, "/PGM/CPU%u/RZ/Trap0e/Time2/HandlerPhysical", "Profiling of the Trap0eHandler body when the cause is a physical handler.");
1380 PGM_REG_PROFILE(&pCpuStats->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.");
1381 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2InvalidPhys, "/PGM/CPU%u/RZ/Trap0e/Time2/InvalidPhys", "Profiling of the Trap0eHandler body when the cause is access to an invalid physical guest address.");
1382 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2MakeWritable, "/PGM/CPU%u/RZ/Trap0e/Time2/MakeWritable", "Profiling of the Trap0eHandler body when the cause is that a page needed to be made writeable.");
1383 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2Misc, "/PGM/CPU%u/RZ/Trap0e/Time2/Misc", "Profiling of the Trap0eHandler body when the cause is not known.");
1384 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2OutOfSync, "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSync", "Profiling of the Trap0eHandler body when the cause is an out-of-sync page.");
1385 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2OutOfSyncHndPhys, "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSyncHndPhys", "Profiling of the Trap0eHandler body when the cause is an out-of-sync physical handler page.");
1386 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2OutOfSyncHndObs, "/PGM/CPU%u/RZ/Trap0e/Time2/OutOfSyncObsHnd", "Profiling of the Trap0eHandler body when the cause is an obsolete handler page.");
1387 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2SyncPT, "/PGM/CPU%u/RZ/Trap0e/Time2/SyncPT", "Profiling of the Trap0eHandler body when the cause is lazy syncing of a PT.");
1388 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2WPEmulation, "/PGM/CPU%u/RZ/Trap0e/Time2/WPEmulation", "Profiling of the Trap0eHandler body when the cause is CR0.WP emulation.");
1389 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2Wp0RoUsHack, "/PGM/CPU%u/RZ/Trap0e/Time2/WP0R0USHack", "Profiling of the Trap0eHandler body when the cause is CR0.WP and netware hack to be enabled.");
1390 PGM_REG_PROFILE(&pCpuStats->StatRZTrap0eTime2Wp0RoUsUnhack, "/PGM/CPU%u/RZ/Trap0e/Time2/WP0R0USUnhack", "Profiling of the Trap0eHandler body when the cause is CR0.WP and netware hack to be disabled.");
1391 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eConflicts, "/PGM/CPU%u/RZ/Trap0e/Conflicts", "The number of times #PF was caused by an undetected conflict.");
1392 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersOutOfSync, "/PGM/CPU%u/RZ/Trap0e/Handlers/OutOfSync", "Number of traps due to out-of-sync handled pages.");
1393 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersPhysAll, "/PGM/CPU%u/RZ/Trap0e/Handlers/PhysAll", "Number of traps due to physical all-access handlers.");
1394 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersPhysAllOpt, "/PGM/CPU%u/RZ/Trap0e/Handlers/PhysAllOpt", "Number of the physical all-access handler traps using the optimization.");
1395 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersPhysWrite, "/PGM/CPU%u/RZ/Trap0e/Handlers/PhysWrite", "Number of traps due to physical write-access handlers.");
1396 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersUnhandled, "/PGM/CPU%u/RZ/Trap0e/Handlers/Unhandled", "Number of traps due to access outside range of monitored page(s).");
1397 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eHandlersInvalid, "/PGM/CPU%u/RZ/Trap0e/Handlers/Invalid", "Number of traps due to access to invalid physical memory.");
1398 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eUSNotPresentRead, "/PGM/CPU%u/RZ/Trap0e/Err/User/NPRead", "Number of user mode not present read page faults.");
1399 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eUSNotPresentWrite, "/PGM/CPU%u/RZ/Trap0e/Err/User/NPWrite", "Number of user mode not present write page faults.");
1400 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eUSWrite, "/PGM/CPU%u/RZ/Trap0e/Err/User/Write", "Number of user mode write page faults.");
1401 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eUSReserved, "/PGM/CPU%u/RZ/Trap0e/Err/User/Reserved", "Number of user mode reserved bit page faults.");
1402 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eUSNXE, "/PGM/CPU%u/RZ/Trap0e/Err/User/NXE", "Number of user mode NXE page faults.");
1403 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eUSRead, "/PGM/CPU%u/RZ/Trap0e/Err/User/Read", "Number of user mode read page faults.");
1404 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eSVNotPresentRead, "/PGM/CPU%u/RZ/Trap0e/Err/Supervisor/NPRead", "Number of supervisor mode not present read page faults.");
1405 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eSVNotPresentWrite, "/PGM/CPU%u/RZ/Trap0e/Err/Supervisor/NPWrite", "Number of supervisor mode not present write page faults.");
1406 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eSVWrite, "/PGM/CPU%u/RZ/Trap0e/Err/Supervisor/Write", "Number of supervisor mode write page faults.");
1407 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eSVReserved, "/PGM/CPU%u/RZ/Trap0e/Err/Supervisor/Reserved", "Number of supervisor mode reserved bit page faults.");
1408 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eSNXE, "/PGM/CPU%u/RZ/Trap0e/Err/Supervisor/NXE", "Number of supervisor mode NXE page faults.");
1409 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eGuestPF, "/PGM/CPU%u/RZ/Trap0e/GuestPF", "Number of real guest page faults.");
1410 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eWPEmulInRZ, "/PGM/CPU%u/RZ/Trap0e/WP/InRZ", "Number of guest page faults due to X86_CR0_WP emulation.");
1411 PGM_REG_COUNTER(&pCpuStats->StatRZTrap0eWPEmulToR3, "/PGM/CPU%u/RZ/Trap0e/WP/ToR3", "Number of guest page faults due to X86_CR0_WP emulation (forward to R3 for emulation).");
1412#if 0 /* rarely useful; leave for debugging. */
1413 for (unsigned j = 0; j < RT_ELEMENTS(pCpuStats->StatRZTrap0ePD); j++)
1414 STAMR3RegisterF(pVM, &pCpuStats->StatRZTrap0ePD[i], STAMTYPE_COUNTER, STAMVISIBILITY_USED, STAMUNIT_OCCURENCES,
1415 "The number of traps in page directory n.", "/PGM/CPU%u/RZ/Trap0e/PD/%04X", i, j);
1416#endif
1417 PGM_REG_COUNTER(&pCpuStats->StatRZGuestCR3WriteHandled, "/PGM/CPU%u/RZ/CR3WriteHandled", "The number of times the Guest CR3 change was successfully handled.");
1418 PGM_REG_COUNTER(&pCpuStats->StatRZGuestCR3WriteUnhandled, "/PGM/CPU%u/RZ/CR3WriteUnhandled", "The number of times the Guest CR3 change was passed back to the recompiler.");
1419 PGM_REG_COUNTER(&pCpuStats->StatRZGuestCR3WriteConflict, "/PGM/CPU%u/RZ/CR3WriteConflict", "The number of times the Guest CR3 monitoring detected a conflict.");
1420 PGM_REG_COUNTER(&pCpuStats->StatRZGuestROMWriteHandled, "/PGM/CPU%u/RZ/ROMWriteHandled", "The number of times the Guest ROM change was successfully handled.");
1421 PGM_REG_COUNTER(&pCpuStats->StatRZGuestROMWriteUnhandled, "/PGM/CPU%u/RZ/ROMWriteUnhandled", "The number of times the Guest ROM change was passed back to the recompiler.");
1422
1423 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapMigrateInvlPg, "/PGM/CPU%u/RZ/DynMap/MigrateInvlPg", "invlpg count in PGMR0DynMapMigrateAutoSet.");
1424 PGM_REG_PROFILE(&pCpuStats->StatRZDynMapGCPageInl, "/PGM/CPU%u/RZ/DynMap/PageGCPageInl", "Calls to pgmR0DynMapGCPageInlined.");
1425 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapGCPageInlHits, "/PGM/CPU%u/RZ/DynMap/PageGCPageInl/Hits", "Hash table lookup hits.");
1426 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapGCPageInlMisses, "/PGM/CPU%u/RZ/DynMap/PageGCPageInl/Misses", "Misses that falls back to the code common.");
1427 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapGCPageInlRamHits, "/PGM/CPU%u/RZ/DynMap/PageGCPageInl/RamHits", "1st ram range hits.");
1428 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapGCPageInlRamMisses, "/PGM/CPU%u/RZ/DynMap/PageGCPageInl/RamMisses", "1st ram range misses, takes slow path.");
1429 PGM_REG_PROFILE(&pCpuStats->StatRZDynMapHCPageInl, "/PGM/CPU%u/RZ/DynMap/PageHCPageInl", "Calls to pgmRZDynMapHCPageInlined.");
1430 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapHCPageInlHits, "/PGM/CPU%u/RZ/DynMap/PageHCPageInl/Hits", "Hash table lookup hits.");
1431 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapHCPageInlMisses, "/PGM/CPU%u/RZ/DynMap/PageHCPageInl/Misses", "Misses that falls back to the code common.");
1432 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapPage, "/PGM/CPU%u/RZ/DynMap/Page", "Calls to pgmR0DynMapPage");
1433 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapSetOptimize, "/PGM/CPU%u/RZ/DynMap/Page/SetOptimize", "Calls to pgmRZDynMapOptimizeAutoSet.");
1434 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapSetSearchFlushes, "/PGM/CPU%u/RZ/DynMap/Page/SetSearchFlushes", "Set search restoring to subset flushes.");
1435 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapSetSearchHits, "/PGM/CPU%u/RZ/DynMap/Page/SetSearchHits", "Set search hits.");
1436 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapSetSearchMisses, "/PGM/CPU%u/RZ/DynMap/Page/SetSearchMisses", "Set search misses.");
1437 PGM_REG_PROFILE(&pCpuStats->StatRZDynMapHCPage, "/PGM/CPU%u/RZ/DynMap/Page/HCPage", "Calls to pgmRZDynMapHCPageCommon (ring-0).");
1438 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapPageHits0, "/PGM/CPU%u/RZ/DynMap/Page/Hits0", "Hits at iPage+0");
1439 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapPageHits1, "/PGM/CPU%u/RZ/DynMap/Page/Hits1", "Hits at iPage+1");
1440 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapPageHits2, "/PGM/CPU%u/RZ/DynMap/Page/Hits2", "Hits at iPage+2");
1441 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapPageInvlPg, "/PGM/CPU%u/RZ/DynMap/Page/InvlPg", "invlpg count in pgmR0DynMapPageSlow.");
1442 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapPageSlow, "/PGM/CPU%u/RZ/DynMap/Page/Slow", "Calls to pgmR0DynMapPageSlow - subtract this from pgmR0DynMapPage to get 1st level hits.");
1443 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapPageSlowLoopHits, "/PGM/CPU%u/RZ/DynMap/Page/SlowLoopHits" , "Hits in the loop path.");
1444 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapPageSlowLoopMisses, "/PGM/CPU%u/RZ/DynMap/Page/SlowLoopMisses", "Misses in the loop path. NonLoopMisses = Slow - SlowLoopHit - SlowLoopMisses");
1445 //PGM_REG_COUNTER(&pCpuStats->StatRZDynMapPageSlowLostHits, "/PGM/CPU%u/R0/DynMap/Page/SlowLostHits", "Lost hits.");
1446 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapSubsets, "/PGM/CPU%u/RZ/DynMap/Subsets", "Times PGMRZDynMapPushAutoSubset was called.");
1447 PGM_REG_COUNTER(&pCpuStats->StatRZDynMapPopFlushes, "/PGM/CPU%u/RZ/DynMap/SubsetPopFlushes", "Times PGMRZDynMapPopAutoSubset flushes the subset.");
1448 PGM_REG_COUNTER(&pCpuStats->aStatRZDynMapSetFilledPct[0], "/PGM/CPU%u/RZ/DynMap/SetFilledPct000..09", "00-09% filled (RC: min(set-size, dynmap-size))");
1449 PGM_REG_COUNTER(&pCpuStats->aStatRZDynMapSetFilledPct[1], "/PGM/CPU%u/RZ/DynMap/SetFilledPct010..19", "10-19% filled (RC: min(set-size, dynmap-size))");
1450 PGM_REG_COUNTER(&pCpuStats->aStatRZDynMapSetFilledPct[2], "/PGM/CPU%u/RZ/DynMap/SetFilledPct020..29", "20-29% filled (RC: min(set-size, dynmap-size))");
1451 PGM_REG_COUNTER(&pCpuStats->aStatRZDynMapSetFilledPct[3], "/PGM/CPU%u/RZ/DynMap/SetFilledPct030..39", "30-39% filled (RC: min(set-size, dynmap-size))");
1452 PGM_REG_COUNTER(&pCpuStats->aStatRZDynMapSetFilledPct[4], "/PGM/CPU%u/RZ/DynMap/SetFilledPct040..49", "40-49% filled (RC: min(set-size, dynmap-size))");
1453 PGM_REG_COUNTER(&pCpuStats->aStatRZDynMapSetFilledPct[5], "/PGM/CPU%u/RZ/DynMap/SetFilledPct050..59", "50-59% filled (RC: min(set-size, dynmap-size))");
1454 PGM_REG_COUNTER(&pCpuStats->aStatRZDynMapSetFilledPct[6], "/PGM/CPU%u/RZ/DynMap/SetFilledPct060..69", "60-69% filled (RC: min(set-size, dynmap-size))");
1455 PGM_REG_COUNTER(&pCpuStats->aStatRZDynMapSetFilledPct[7], "/PGM/CPU%u/RZ/DynMap/SetFilledPct070..79", "70-79% filled (RC: min(set-size, dynmap-size))");
1456 PGM_REG_COUNTER(&pCpuStats->aStatRZDynMapSetFilledPct[8], "/PGM/CPU%u/RZ/DynMap/SetFilledPct080..89", "80-89% filled (RC: min(set-size, dynmap-size))");
1457 PGM_REG_COUNTER(&pCpuStats->aStatRZDynMapSetFilledPct[9], "/PGM/CPU%u/RZ/DynMap/SetFilledPct090..99", "90-99% filled (RC: min(set-size, dynmap-size))");
1458 PGM_REG_COUNTER(&pCpuStats->aStatRZDynMapSetFilledPct[10], "/PGM/CPU%u/RZ/DynMap/SetFilledPct100", "100% filled (RC: min(set-size, dynmap-size))");
1459
1460 /* HC only: */
1461
1462 /* RZ & R3: */
1463 PGM_REG_PROFILE(&pCpuStats->StatRZSyncCR3, "/PGM/CPU%u/RZ/SyncCR3", "Profiling of the PGMSyncCR3() body.");
1464 PGM_REG_PROFILE(&pCpuStats->StatRZSyncCR3Handlers, "/PGM/CPU%u/RZ/SyncCR3/Handlers", "Profiling of the PGMSyncCR3() update handler section.");
1465 PGM_REG_COUNTER(&pCpuStats->StatRZSyncCR3Global, "/PGM/CPU%u/RZ/SyncCR3/Global", "The number of global CR3 syncs.");
1466 PGM_REG_COUNTER(&pCpuStats->StatRZSyncCR3NotGlobal, "/PGM/CPU%u/RZ/SyncCR3/NotGlobal", "The number of non-global CR3 syncs.");
1467 PGM_REG_COUNTER(&pCpuStats->StatRZSyncCR3DstCacheHit, "/PGM/CPU%u/RZ/SyncCR3/DstChacheHit", "The number of times we got some kind of a cache hit.");
1468 PGM_REG_COUNTER(&pCpuStats->StatRZSyncCR3DstFreed, "/PGM/CPU%u/RZ/SyncCR3/DstFreed", "The number of times we've had to free a shadow entry.");
1469 PGM_REG_COUNTER(&pCpuStats->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.");
1470 PGM_REG_COUNTER(&pCpuStats->StatRZSyncCR3DstNotPresent, "/PGM/CPU%u/RZ/SyncCR3/DstNotPresent", "The number of times we've encountered a not present shadow entry for a present guest entry.");
1471 PGM_REG_COUNTER(&pCpuStats->StatRZSyncCR3DstSkippedGlobalPD, "/PGM/CPU%u/RZ/SyncCR3/DstSkippedGlobalPD", "The number of times a global page directory wasn't flushed.");
1472 PGM_REG_COUNTER(&pCpuStats->StatRZSyncCR3DstSkippedGlobalPT, "/PGM/CPU%u/RZ/SyncCR3/DstSkippedGlobalPT", "The number of times a page table with only global entries wasn't flushed.");
1473 PGM_REG_PROFILE(&pCpuStats->StatRZSyncPT, "/PGM/CPU%u/RZ/SyncPT", "Profiling of the pfnSyncPT() body.");
1474 PGM_REG_COUNTER(&pCpuStats->StatRZSyncPTFailed, "/PGM/CPU%u/RZ/SyncPT/Failed", "The number of times pfnSyncPT() failed.");
1475 PGM_REG_COUNTER(&pCpuStats->StatRZSyncPT4K, "/PGM/CPU%u/RZ/SyncPT/4K", "Nr of 4K PT syncs");
1476 PGM_REG_COUNTER(&pCpuStats->StatRZSyncPT4M, "/PGM/CPU%u/RZ/SyncPT/4M", "Nr of 4M PT syncs");
1477 PGM_REG_COUNTER(&pCpuStats->StatRZSyncPagePDNAs, "/PGM/CPU%u/RZ/SyncPagePDNAs", "The number of time we've marked a PD not present from SyncPage to virtualize the accessed bit.");
1478 PGM_REG_COUNTER(&pCpuStats->StatRZSyncPagePDOutOfSync, "/PGM/CPU%u/RZ/SyncPagePDOutOfSync", "The number of time we've encountered an out-of-sync PD in SyncPage.");
1479 PGM_REG_COUNTER(&pCpuStats->StatRZAccessedPage, "/PGM/CPU%u/RZ/AccessedPage", "The number of pages marked not present for accessed bit emulation.");
1480 PGM_REG_PROFILE(&pCpuStats->StatRZDirtyBitTracking, "/PGM/CPU%u/RZ/DirtyPage", "Profiling the dirty bit tracking in CheckPageFault().");
1481 PGM_REG_COUNTER(&pCpuStats->StatRZDirtyPage, "/PGM/CPU%u/RZ/DirtyPage/Mark", "The number of pages marked read-only for dirty bit tracking.");
1482 PGM_REG_COUNTER(&pCpuStats->StatRZDirtyPageBig, "/PGM/CPU%u/RZ/DirtyPage/MarkBig", "The number of 4MB pages marked read-only for dirty bit tracking.");
1483 PGM_REG_COUNTER(&pCpuStats->StatRZDirtyPageSkipped, "/PGM/CPU%u/RZ/DirtyPage/Skipped", "The number of pages already dirty or readonly.");
1484 PGM_REG_COUNTER(&pCpuStats->StatRZDirtyPageTrap, "/PGM/CPU%u/RZ/DirtyPage/Trap", "The number of traps generated for dirty bit tracking.");
1485 PGM_REG_COUNTER(&pCpuStats->StatRZDirtyPageStale, "/PGM/CPU%u/RZ/DirtyPage/Stale", "The number of traps generated for dirty bit tracking (stale tlb entries).");
1486 PGM_REG_COUNTER(&pCpuStats->StatRZDirtiedPage, "/PGM/CPU%u/RZ/DirtyPage/SetDirty", "The number of pages marked dirty because of write accesses.");
1487 PGM_REG_COUNTER(&pCpuStats->StatRZDirtyTrackRealPF, "/PGM/CPU%u/RZ/DirtyPage/RealPF", "The number of real pages faults during dirty bit tracking.");
1488 PGM_REG_COUNTER(&pCpuStats->StatRZPageAlreadyDirty, "/PGM/CPU%u/RZ/DirtyPage/AlreadySet", "The number of pages already marked dirty because of write accesses.");
1489 PGM_REG_PROFILE(&pCpuStats->StatRZInvalidatePage, "/PGM/CPU%u/RZ/InvalidatePage", "PGMInvalidatePage() profiling.");
1490 PGM_REG_COUNTER(&pCpuStats->StatRZInvalidatePage4KBPages, "/PGM/CPU%u/RZ/InvalidatePage/4KBPages", "The number of times PGMInvalidatePage() was called for a 4KB page.");
1491 PGM_REG_COUNTER(&pCpuStats->StatRZInvalidatePage4MBPages, "/PGM/CPU%u/RZ/InvalidatePage/4MBPages", "The number of times PGMInvalidatePage() was called for a 4MB page.");
1492 PGM_REG_COUNTER(&pCpuStats->StatRZInvalidatePage4MBPagesSkip, "/PGM/CPU%u/RZ/InvalidatePage/4MBPagesSkip","The number of times PGMInvalidatePage() skipped a 4MB page.");
1493 PGM_REG_COUNTER(&pCpuStats->StatRZInvalidatePagePDNAs, "/PGM/CPU%u/RZ/InvalidatePage/PDNAs", "The number of times PGMInvalidatePage() was called for a not accessed page directory.");
1494 PGM_REG_COUNTER(&pCpuStats->StatRZInvalidatePagePDNPs, "/PGM/CPU%u/RZ/InvalidatePage/PDNPs", "The number of times PGMInvalidatePage() was called for a not present page directory.");
1495 PGM_REG_COUNTER(&pCpuStats->StatRZInvalidatePagePDOutOfSync, "/PGM/CPU%u/RZ/InvalidatePage/PDOutOfSync", "The number of times PGMInvalidatePage() was called for an out of sync page directory.");
1496 PGM_REG_COUNTER(&pCpuStats->StatRZInvalidatePageSizeChanges, "/PGM/CPU%u/RZ/InvalidatePage/SizeChanges", "The number of times PGMInvalidatePage() was called on a page size change (4KB <-> 2/4MB).");
1497 PGM_REG_COUNTER(&pCpuStats->StatRZInvalidatePageSkipped, "/PGM/CPU%u/RZ/InvalidatePage/Skipped", "The number of times PGMInvalidatePage() was skipped due to not present shw or pending pending SyncCR3.");
1498 PGM_REG_COUNTER(&pCpuStats->StatRZPageOutOfSyncSupervisor, "/PGM/CPU%u/RZ/OutOfSync/SuperVisor", "Number of traps due to pages out of sync (P) and times VerifyAccessSyncPage calls SyncPage.");
1499 PGM_REG_COUNTER(&pCpuStats->StatRZPageOutOfSyncUser, "/PGM/CPU%u/RZ/OutOfSync/User", "Number of traps due to pages out of sync (P) and times VerifyAccessSyncPage calls SyncPage.");
1500 PGM_REG_COUNTER(&pCpuStats->StatRZPageOutOfSyncSupervisorWrite,"/PGM/CPU%u/RZ/OutOfSync/SuperVisorWrite", "Number of traps due to pages out of sync (RW) and times VerifyAccessSyncPage calls SyncPage.");
1501 PGM_REG_COUNTER(&pCpuStats->StatRZPageOutOfSyncUserWrite, "/PGM/CPU%u/RZ/OutOfSync/UserWrite", "Number of traps due to pages out of sync (RW) and times VerifyAccessSyncPage calls SyncPage.");
1502 PGM_REG_COUNTER(&pCpuStats->StatRZPageOutOfSyncBallloon, "/PGM/CPU%u/RZ/OutOfSync/Balloon", "The number of times a ballooned page was accessed (read).");
1503 PGM_REG_PROFILE(&pCpuStats->StatRZPrefetch, "/PGM/CPU%u/RZ/Prefetch", "PGMPrefetchPage profiling.");
1504 PGM_REG_PROFILE(&pCpuStats->StatRZFlushTLB, "/PGM/CPU%u/RZ/FlushTLB", "Profiling of the PGMFlushTLB() body.");
1505 PGM_REG_COUNTER(&pCpuStats->StatRZFlushTLBNewCR3, "/PGM/CPU%u/RZ/FlushTLB/NewCR3", "The number of times PGMFlushTLB was called with a new CR3, non-global. (switch)");
1506 PGM_REG_COUNTER(&pCpuStats->StatRZFlushTLBNewCR3Global, "/PGM/CPU%u/RZ/FlushTLB/NewCR3Global", "The number of times PGMFlushTLB was called with a new CR3, global. (switch)");
1507 PGM_REG_COUNTER(&pCpuStats->StatRZFlushTLBSameCR3, "/PGM/CPU%u/RZ/FlushTLB/SameCR3", "The number of times PGMFlushTLB was called with the same CR3, non-global. (flush)");
1508 PGM_REG_COUNTER(&pCpuStats->StatRZFlushTLBSameCR3Global, "/PGM/CPU%u/RZ/FlushTLB/SameCR3Global", "The number of times PGMFlushTLB was called with the same CR3, global. (flush)");
1509 PGM_REG_PROFILE(&pCpuStats->StatRZGstModifyPage, "/PGM/CPU%u/RZ/GstModifyPage", "Profiling of the PGMGstModifyPage() body.");
1510
1511 PGM_REG_PROFILE(&pCpuStats->StatR3SyncCR3, "/PGM/CPU%u/R3/SyncCR3", "Profiling of the PGMSyncCR3() body.");
1512 PGM_REG_PROFILE(&pCpuStats->StatR3SyncCR3Handlers, "/PGM/CPU%u/R3/SyncCR3/Handlers", "Profiling of the PGMSyncCR3() update handler section.");
1513 PGM_REG_COUNTER(&pCpuStats->StatR3SyncCR3Global, "/PGM/CPU%u/R3/SyncCR3/Global", "The number of global CR3 syncs.");
1514 PGM_REG_COUNTER(&pCpuStats->StatR3SyncCR3NotGlobal, "/PGM/CPU%u/R3/SyncCR3/NotGlobal", "The number of non-global CR3 syncs.");
1515 PGM_REG_COUNTER(&pCpuStats->StatR3SyncCR3DstCacheHit, "/PGM/CPU%u/R3/SyncCR3/DstChacheHit", "The number of times we got some kind of a cache hit.");
1516 PGM_REG_COUNTER(&pCpuStats->StatR3SyncCR3DstFreed, "/PGM/CPU%u/R3/SyncCR3/DstFreed", "The number of times we've had to free a shadow entry.");
1517 PGM_REG_COUNTER(&pCpuStats->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.");
1518 PGM_REG_COUNTER(&pCpuStats->StatR3SyncCR3DstNotPresent, "/PGM/CPU%u/R3/SyncCR3/DstNotPresent", "The number of times we've encountered a not present shadow entry for a present guest entry.");
1519 PGM_REG_COUNTER(&pCpuStats->StatR3SyncCR3DstSkippedGlobalPD, "/PGM/CPU%u/R3/SyncCR3/DstSkippedGlobalPD", "The number of times a global page directory wasn't flushed.");
1520 PGM_REG_COUNTER(&pCpuStats->StatR3SyncCR3DstSkippedGlobalPT, "/PGM/CPU%u/R3/SyncCR3/DstSkippedGlobalPT", "The number of times a page table with only global entries wasn't flushed.");
1521 PGM_REG_PROFILE(&pCpuStats->StatR3SyncPT, "/PGM/CPU%u/R3/SyncPT", "Profiling of the pfnSyncPT() body.");
1522 PGM_REG_COUNTER(&pCpuStats->StatR3SyncPTFailed, "/PGM/CPU%u/R3/SyncPT/Failed", "The number of times pfnSyncPT() failed.");
1523 PGM_REG_COUNTER(&pCpuStats->StatR3SyncPT4K, "/PGM/CPU%u/R3/SyncPT/4K", "Nr of 4K PT syncs");
1524 PGM_REG_COUNTER(&pCpuStats->StatR3SyncPT4M, "/PGM/CPU%u/R3/SyncPT/4M", "Nr of 4M PT syncs");
1525 PGM_REG_COUNTER(&pCpuStats->StatR3SyncPagePDNAs, "/PGM/CPU%u/R3/SyncPagePDNAs", "The number of time we've marked a PD not present from SyncPage to virtualize the accessed bit.");
1526 PGM_REG_COUNTER(&pCpuStats->StatR3SyncPagePDOutOfSync, "/PGM/CPU%u/R3/SyncPagePDOutOfSync", "The number of time we've encountered an out-of-sync PD in SyncPage.");
1527 PGM_REG_COUNTER(&pCpuStats->StatR3AccessedPage, "/PGM/CPU%u/R3/AccessedPage", "The number of pages marked not present for accessed bit emulation.");
1528 PGM_REG_PROFILE(&pCpuStats->StatR3DirtyBitTracking, "/PGM/CPU%u/R3/DirtyPage", "Profiling the dirty bit tracking in CheckPageFault().");
1529 PGM_REG_COUNTER(&pCpuStats->StatR3DirtyPage, "/PGM/CPU%u/R3/DirtyPage/Mark", "The number of pages marked read-only for dirty bit tracking.");
1530 PGM_REG_COUNTER(&pCpuStats->StatR3DirtyPageBig, "/PGM/CPU%u/R3/DirtyPage/MarkBig", "The number of 4MB pages marked read-only for dirty bit tracking.");
1531 PGM_REG_COUNTER(&pCpuStats->StatR3DirtyPageSkipped, "/PGM/CPU%u/R3/DirtyPage/Skipped", "The number of pages already dirty or readonly.");
1532 PGM_REG_COUNTER(&pCpuStats->StatR3DirtyPageTrap, "/PGM/CPU%u/R3/DirtyPage/Trap", "The number of traps generated for dirty bit tracking.");
1533 PGM_REG_COUNTER(&pCpuStats->StatR3DirtiedPage, "/PGM/CPU%u/R3/DirtyPage/SetDirty", "The number of pages marked dirty because of write accesses.");
1534 PGM_REG_COUNTER(&pCpuStats->StatR3DirtyTrackRealPF, "/PGM/CPU%u/R3/DirtyPage/RealPF", "The number of real pages faults during dirty bit tracking.");
1535 PGM_REG_COUNTER(&pCpuStats->StatR3PageAlreadyDirty, "/PGM/CPU%u/R3/DirtyPage/AlreadySet", "The number of pages already marked dirty because of write accesses.");
1536 PGM_REG_PROFILE(&pCpuStats->StatR3InvalidatePage, "/PGM/CPU%u/R3/InvalidatePage", "PGMInvalidatePage() profiling.");
1537 PGM_REG_COUNTER(&pCpuStats->StatR3InvalidatePage4KBPages, "/PGM/CPU%u/R3/InvalidatePage/4KBPages", "The number of times PGMInvalidatePage() was called for a 4KB page.");
1538 PGM_REG_COUNTER(&pCpuStats->StatR3InvalidatePage4MBPages, "/PGM/CPU%u/R3/InvalidatePage/4MBPages", "The number of times PGMInvalidatePage() was called for a 4MB page.");
1539 PGM_REG_COUNTER(&pCpuStats->StatR3InvalidatePage4MBPagesSkip, "/PGM/CPU%u/R3/InvalidatePage/4MBPagesSkip","The number of times PGMInvalidatePage() skipped a 4MB page.");
1540 PGM_REG_COUNTER(&pCpuStats->StatR3InvalidatePagePDNAs, "/PGM/CPU%u/R3/InvalidatePage/PDNAs", "The number of times PGMInvalidatePage() was called for a not accessed page directory.");
1541 PGM_REG_COUNTER(&pCpuStats->StatR3InvalidatePagePDNPs, "/PGM/CPU%u/R3/InvalidatePage/PDNPs", "The number of times PGMInvalidatePage() was called for a not present page directory.");
1542 PGM_REG_COUNTER(&pCpuStats->StatR3InvalidatePagePDOutOfSync, "/PGM/CPU%u/R3/InvalidatePage/PDOutOfSync", "The number of times PGMInvalidatePage() was called for an out of sync page directory.");
1543 PGM_REG_COUNTER(&pCpuStats->StatR3InvalidatePageSizeChanges, "/PGM/CPU%u/R3/InvalidatePage/SizeChanges", "The number of times PGMInvalidatePage() was called on a page size change (4KB <-> 2/4MB).");
1544 PGM_REG_COUNTER(&pCpuStats->StatR3InvalidatePageSkipped, "/PGM/CPU%u/R3/InvalidatePage/Skipped", "The number of times PGMInvalidatePage() was skipped due to not present shw or pending pending SyncCR3.");
1545 PGM_REG_COUNTER(&pCpuStats->StatR3PageOutOfSyncSupervisor, "/PGM/CPU%u/R3/OutOfSync/SuperVisor", "Number of traps due to pages out of sync and times VerifyAccessSyncPage calls SyncPage.");
1546 PGM_REG_COUNTER(&pCpuStats->StatR3PageOutOfSyncUser, "/PGM/CPU%u/R3/OutOfSync/User", "Number of traps due to pages out of sync and times VerifyAccessSyncPage calls SyncPage.");
1547 PGM_REG_COUNTER(&pCpuStats->StatR3PageOutOfSyncBallloon, "/PGM/CPU%u/R3/OutOfSync/Balloon", "The number of times a ballooned page was accessed (read).");
1548 PGM_REG_PROFILE(&pCpuStats->StatR3Prefetch, "/PGM/CPU%u/R3/Prefetch", "PGMPrefetchPage profiling.");
1549 PGM_REG_PROFILE(&pCpuStats->StatR3FlushTLB, "/PGM/CPU%u/R3/FlushTLB", "Profiling of the PGMFlushTLB() body.");
1550 PGM_REG_COUNTER(&pCpuStats->StatR3FlushTLBNewCR3, "/PGM/CPU%u/R3/FlushTLB/NewCR3", "The number of times PGMFlushTLB was called with a new CR3, non-global. (switch)");
1551 PGM_REG_COUNTER(&pCpuStats->StatR3FlushTLBNewCR3Global, "/PGM/CPU%u/R3/FlushTLB/NewCR3Global", "The number of times PGMFlushTLB was called with a new CR3, global. (switch)");
1552 PGM_REG_COUNTER(&pCpuStats->StatR3FlushTLBSameCR3, "/PGM/CPU%u/R3/FlushTLB/SameCR3", "The number of times PGMFlushTLB was called with the same CR3, non-global. (flush)");
1553 PGM_REG_COUNTER(&pCpuStats->StatR3FlushTLBSameCR3Global, "/PGM/CPU%u/R3/FlushTLB/SameCR3Global", "The number of times PGMFlushTLB was called with the same CR3, global. (flush)");
1554 PGM_REG_PROFILE(&pCpuStats->StatR3GstModifyPage, "/PGM/CPU%u/R3/GstModifyPage", "Profiling of the PGMGstModifyPage() body.");
1555#endif /* VBOX_WITH_STATISTICS */
1556
1557#undef PGM_REG_PROFILE
1558#undef PGM_REG_COUNTER
1559
1560 }
1561
1562 return VINF_SUCCESS;
1563}
1564
1565
1566/**
1567 * Ring-3 init finalizing.
1568 *
1569 * @returns VBox status code.
1570 * @param pVM The cross context VM structure.
1571 */
1572VMMR3DECL(int) PGMR3InitFinalize(PVM pVM)
1573{
1574 /*
1575 * Determine the max physical address width (MAXPHYADDR) and apply it to
1576 * all the mask members and stuff.
1577 */
1578 uint32_t cMaxPhysAddrWidth;
1579 uint32_t uMaxExtLeaf = ASMCpuId_EAX(0x80000000);
1580 if ( uMaxExtLeaf >= 0x80000008
1581 && uMaxExtLeaf <= 0x80000fff)
1582 {
1583 cMaxPhysAddrWidth = ASMCpuId_EAX(0x80000008) & 0xff;
1584 LogRel(("PGM: The CPU physical address width is %u bits\n", cMaxPhysAddrWidth));
1585 cMaxPhysAddrWidth = RT_MIN(52, cMaxPhysAddrWidth);
1586 pVM->pgm.s.fLessThan52PhysicalAddressBits = cMaxPhysAddrWidth < 52;
1587 for (uint32_t iBit = cMaxPhysAddrWidth; iBit < 52; iBit++)
1588 pVM->pgm.s.HCPhysInvMmioPg |= RT_BIT_64(iBit);
1589 }
1590 else
1591 {
1592 LogRel(("PGM: ASSUMING CPU physical address width of 48 bits (uMaxExtLeaf=%#x)\n", uMaxExtLeaf));
1593 cMaxPhysAddrWidth = 48;
1594 pVM->pgm.s.fLessThan52PhysicalAddressBits = true;
1595 pVM->pgm.s.HCPhysInvMmioPg |= UINT64_C(0x000f0000000000);
1596 }
1597 Assert(pVM->cpum.ro.GuestFeatures.cMaxPhysAddrWidth == cMaxPhysAddrWidth);
1598
1599 /** @todo query from CPUM. */
1600 pVM->pgm.s.GCPhysInvAddrMask = 0;
1601 for (uint32_t iBit = cMaxPhysAddrWidth; iBit < 64; iBit++)
1602 pVM->pgm.s.GCPhysInvAddrMask |= RT_BIT_64(iBit);
1603
1604 /*
1605 * Initialize the invalid paging entry masks, assuming NX is disabled.
1606 */
1607 uint64_t fMbzPageFrameMask = pVM->pgm.s.GCPhysInvAddrMask & UINT64_C(0x000ffffffffff000);
1608#ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
1609 uint64_t const fEptVpidCap = CPUMGetGuestIa32VmxEptVpidCap(pVM->apCpusR3[0]); /* should be identical for all VCPUs. */
1610 uint64_t const fGstEptMbzBigPdeMask = EPT_PDE2M_MBZ_MASK
1611 | (RT_BF_GET(fEptVpidCap, VMX_BF_EPT_VPID_CAP_PDE_2M) ^ 1) << EPT_E_BIT_LEAF;
1612 uint64_t const fGstEptMbzBigPdpteMask = EPT_PDPTE1G_MBZ_MASK
1613 | (RT_BF_GET(fEptVpidCap, VMX_BF_EPT_VPID_CAP_PDPTE_1G) ^ 1) << EPT_E_BIT_LEAF;
1614#endif
1615 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1616 {
1617 PVMCPU pVCpu = pVM->apCpusR3[idCpu];
1618
1619 /** @todo The manuals are not entirely clear whether the physical
1620 * address width is relevant. See table 5-9 in the intel
1621 * manual vs the PDE4M descriptions. Write testcase (NP). */
1622 pVCpu->pgm.s.fGst32BitMbzBigPdeMask = ((uint32_t)(fMbzPageFrameMask >> (32 - 13)) & X86_PDE4M_PG_HIGH_MASK)
1623 | X86_PDE4M_MBZ_MASK;
1624
1625 pVCpu->pgm.s.fGstPaeMbzPteMask = fMbzPageFrameMask | X86_PTE_PAE_MBZ_MASK_NO_NX;
1626 pVCpu->pgm.s.fGstPaeMbzPdeMask = fMbzPageFrameMask | X86_PDE_PAE_MBZ_MASK_NO_NX;
1627 pVCpu->pgm.s.fGstPaeMbzBigPdeMask = fMbzPageFrameMask | X86_PDE2M_PAE_MBZ_MASK_NO_NX;
1628 pVCpu->pgm.s.fGstPaeMbzPdpeMask = fMbzPageFrameMask | X86_PDPE_PAE_MBZ_MASK;
1629
1630 pVCpu->pgm.s.fGstAmd64MbzPteMask = fMbzPageFrameMask | X86_PTE_LM_MBZ_MASK_NO_NX;
1631 pVCpu->pgm.s.fGstAmd64MbzPdeMask = fMbzPageFrameMask | X86_PDE_LM_MBZ_MASK_NX;
1632 pVCpu->pgm.s.fGstAmd64MbzBigPdeMask = fMbzPageFrameMask | X86_PDE2M_LM_MBZ_MASK_NX;
1633 pVCpu->pgm.s.fGstAmd64MbzPdpeMask = fMbzPageFrameMask | X86_PDPE_LM_MBZ_MASK_NO_NX;
1634 pVCpu->pgm.s.fGstAmd64MbzBigPdpeMask = fMbzPageFrameMask | X86_PDPE1G_LM_MBZ_MASK_NO_NX;
1635 pVCpu->pgm.s.fGstAmd64MbzPml4eMask = fMbzPageFrameMask | X86_PML4E_MBZ_MASK_NO_NX;
1636
1637 pVCpu->pgm.s.fGst64ShadowedPteMask = X86_PTE_P | X86_PTE_RW | X86_PTE_US | X86_PTE_G | X86_PTE_A | X86_PTE_D;
1638 pVCpu->pgm.s.fGst64ShadowedPdeMask = X86_PDE_P | X86_PDE_RW | X86_PDE_US | X86_PDE_A;
1639 pVCpu->pgm.s.fGst64ShadowedBigPdeMask = X86_PDE4M_P | X86_PDE4M_RW | X86_PDE4M_US | X86_PDE4M_A;
1640 pVCpu->pgm.s.fGst64ShadowedBigPde4PteMask =
1641 X86_PDE4M_P | X86_PDE4M_RW | X86_PDE4M_US | X86_PDE4M_G | X86_PDE4M_A | X86_PDE4M_D;
1642 pVCpu->pgm.s.fGstAmd64ShadowedPdpeMask = X86_PDPE_P | X86_PDPE_RW | X86_PDPE_US | X86_PDPE_A;
1643 pVCpu->pgm.s.fGstAmd64ShadowedPml4eMask = X86_PML4E_P | X86_PML4E_RW | X86_PML4E_US | X86_PML4E_A;
1644
1645#ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
1646 pVCpu->pgm.s.uEptVpidCapMsr = fEptVpidCap;
1647 pVCpu->pgm.s.fGstEptMbzPteMask = fMbzPageFrameMask | EPT_PTE_MBZ_MASK;
1648 pVCpu->pgm.s.fGstEptMbzPdeMask = fMbzPageFrameMask | EPT_PDE_MBZ_MASK;
1649 pVCpu->pgm.s.fGstEptMbzBigPdeMask = fMbzPageFrameMask | fGstEptMbzBigPdeMask;
1650 pVCpu->pgm.s.fGstEptMbzPdpteMask = fMbzPageFrameMask | EPT_PDPTE_MBZ_MASK;
1651 pVCpu->pgm.s.fGstEptMbzBigPdpteMask = fMbzPageFrameMask | fGstEptMbzBigPdpteMask;
1652 pVCpu->pgm.s.fGstEptMbzPml4eMask = fMbzPageFrameMask | EPT_PML4E_MBZ_MASK;
1653
1654 /* If any of the features (in the assert below) are enabled, we might have to shadow the relevant bits. */
1655 Assert( !pVM->cpum.ro.GuestFeatures.fVmxModeBasedExecuteEpt
1656 && !pVM->cpum.ro.GuestFeatures.fVmxSppEpt
1657 && !pVM->cpum.ro.GuestFeatures.fVmxEptXcptVe);
1658 pVCpu->pgm.s.fGstEptPresentMask = EPT_E_READ | EPT_E_WRITE | EPT_E_EXECUTE;
1659#endif
1660 }
1661
1662 /*
1663 * Note that AMD uses all the 8 reserved bits for the address (so 40 bits in total);
1664 * Intel only goes up to 36 bits, so we stick to 36 as well.
1665 * Update: More recent intel manuals specifies 40 bits just like AMD.
1666 */
1667 uint32_t u32Dummy, u32Features;
1668 CPUMGetGuestCpuId(VMMGetCpu(pVM), 1, 0, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features);
1669 if (u32Features & X86_CPUID_FEATURE_EDX_PSE36)
1670 pVM->pgm.s.GCPhys4MBPSEMask = RT_BIT_64(RT_MAX(36, cMaxPhysAddrWidth)) - 1;
1671 else
1672 pVM->pgm.s.GCPhys4MBPSEMask = RT_BIT_64(32) - 1;
1673
1674 /*
1675 * Allocate memory if we're supposed to do that.
1676 */
1677 int rc = VINF_SUCCESS;
1678 if (pVM->pgm.s.fRamPreAlloc)
1679 rc = pgmR3PhysRamPreAllocate(pVM);
1680
1681 //pgmLogState(pVM);
1682 LogRel(("PGM: PGMR3InitFinalize: 4 MB PSE mask %RGp -> %Rrc\n", pVM->pgm.s.GCPhys4MBPSEMask, rc));
1683 return rc;
1684}
1685
1686
1687/**
1688 * Init phase completed callback.
1689 *
1690 * @returns VBox status code.
1691 * @param pVM The cross context VM structure.
1692 * @param enmWhat What has been completed.
1693 * @thread EMT(0)
1694 */
1695VMMR3_INT_DECL(int) PGMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
1696{
1697 switch (enmWhat)
1698 {
1699 case VMINITCOMPLETED_HM:
1700#ifdef VBOX_WITH_PCI_PASSTHROUGH
1701 if (pVM->pgm.s.fPciPassthrough)
1702 {
1703 AssertLogRelReturn(pVM->pgm.s.fRamPreAlloc, VERR_PCI_PASSTHROUGH_NO_RAM_PREALLOC);
1704 AssertLogRelReturn(HMIsEnabled(pVM), VERR_PCI_PASSTHROUGH_NO_HM);
1705 AssertLogRelReturn(HMIsNestedPagingActive(pVM), VERR_PCI_PASSTHROUGH_NO_NESTED_PAGING);
1706
1707 /*
1708 * Report assignments to the IOMMU (hope that's good enough for now).
1709 */
1710 if (pVM->pgm.s.fPciPassthrough)
1711 {
1712 int rc = VMMR3CallR0(pVM, VMMR0_DO_PGM_PHYS_SETUP_IOMMU, 0, NULL);
1713 AssertRCReturn(rc, rc);
1714 }
1715 }
1716#else
1717 AssertLogRelReturn(!pVM->pgm.s.fPciPassthrough, VERR_PGM_PCI_PASSTHRU_MISCONFIG);
1718#endif
1719 break;
1720
1721 default:
1722 /* shut up gcc */
1723 break;
1724 }
1725
1726 return VINF_SUCCESS;
1727}
1728
1729
1730/**
1731 * Applies relocations to data and code managed by this component.
1732 *
1733 * This function will be called at init and whenever the VMM need to relocate it
1734 * self inside the GC.
1735 *
1736 * @param pVM The cross context VM structure.
1737 * @param offDelta Relocation delta relative to old location.
1738 */
1739VMMR3DECL(void) PGMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
1740{
1741 LogFlow(("PGMR3Relocate: offDelta=%RGv\n", offDelta));
1742
1743 /*
1744 * Paging stuff.
1745 */
1746
1747 /* Shadow, guest and both mode switch & relocation for each VCPU. */
1748 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1749 {
1750 PVMCPU pVCpu = pVM->apCpusR3[i];
1751
1752 uintptr_t idxShw = pVCpu->pgm.s.idxShadowModeData;
1753 if ( idxShw < RT_ELEMENTS(g_aPgmShadowModeData)
1754 && g_aPgmShadowModeData[idxShw].pfnRelocate)
1755 g_aPgmShadowModeData[idxShw].pfnRelocate(pVCpu, offDelta);
1756 else
1757 AssertFailed();
1758
1759 uintptr_t const idxGst = pVCpu->pgm.s.idxGuestModeData;
1760 if ( idxGst < RT_ELEMENTS(g_aPgmGuestModeData)
1761 && g_aPgmGuestModeData[idxGst].pfnRelocate)
1762 g_aPgmGuestModeData[idxGst].pfnRelocate(pVCpu, offDelta);
1763 else
1764 AssertFailed();
1765 }
1766
1767 /*
1768 * Ram ranges.
1769 */
1770 if (pVM->pgm.s.pRamRangesXR3)
1771 pgmR3PhysRelinkRamRanges(pVM);
1772
1773 /*
1774 * The Zero page.
1775 */
1776 pVM->pgm.s.pvZeroPgR0 = MMHyperR3ToR0(pVM, pVM->pgm.s.pvZeroPgR3);
1777 AssertRelease(pVM->pgm.s.pvZeroPgR0 != NIL_RTR0PTR || SUPR3IsDriverless());
1778
1779 /*
1780 * The page pool.
1781 */
1782 pgmR3PoolRelocate(pVM);
1783}
1784
1785
1786/**
1787 * Resets a virtual CPU when unplugged.
1788 *
1789 * @param pVM The cross context VM structure.
1790 * @param pVCpu The cross context virtual CPU structure.
1791 */
1792VMMR3DECL(void) PGMR3ResetCpu(PVM pVM, PVMCPU pVCpu)
1793{
1794 uintptr_t const idxGst = pVCpu->pgm.s.idxGuestModeData;
1795 if ( idxGst < RT_ELEMENTS(g_aPgmGuestModeData)
1796 && g_aPgmGuestModeData[idxGst].pfnExit)
1797 {
1798 int rc = g_aPgmGuestModeData[idxGst].pfnExit(pVCpu);
1799 AssertReleaseRC(rc);
1800 }
1801 pVCpu->pgm.s.GCPhysCR3 = NIL_RTGCPHYS;
1802 pVCpu->pgm.s.GCPhysNstGstCR3 = NIL_RTGCPHYS;
1803
1804 int rc = PGMHCChangeMode(pVM, pVCpu, PGMMODE_REAL);
1805 AssertReleaseRC(rc);
1806
1807 STAM_REL_COUNTER_RESET(&pVCpu->pgm.s.cGuestModeChanges);
1808
1809 pgmR3PoolResetUnpluggedCpu(pVM, pVCpu);
1810
1811 /*
1812 * Re-init other members.
1813 */
1814 pVCpu->pgm.s.fA20Enabled = true;
1815 pVCpu->pgm.s.GCPhysA20Mask = ~((RTGCPHYS)!pVCpu->pgm.s.fA20Enabled << 20);
1816
1817 /*
1818 * Clear the FFs PGM owns.
1819 */
1820 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
1821 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
1822}
1823
1824
1825/**
1826 * The VM is being reset.
1827 *
1828 * For the PGM component this means that any PD write monitors
1829 * needs to be removed.
1830 *
1831 * @param pVM The cross context VM structure.
1832 */
1833VMMR3_INT_DECL(void) PGMR3Reset(PVM pVM)
1834{
1835 LogFlow(("PGMR3Reset:\n"));
1836 VM_ASSERT_EMT(pVM);
1837
1838 PGM_LOCK_VOID(pVM);
1839
1840 /*
1841 * Exit the guest paging mode before the pgm pool gets reset.
1842 * Important to clean up the amd64 case.
1843 */
1844 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1845 {
1846 PVMCPU pVCpu = pVM->apCpusR3[i];
1847 uintptr_t const idxGst = pVCpu->pgm.s.idxGuestModeData;
1848 if ( idxGst < RT_ELEMENTS(g_aPgmGuestModeData)
1849 && g_aPgmGuestModeData[idxGst].pfnExit)
1850 {
1851 int rc = g_aPgmGuestModeData[idxGst].pfnExit(pVCpu);
1852 AssertReleaseRC(rc);
1853 }
1854 pVCpu->pgm.s.GCPhysCR3 = NIL_RTGCPHYS;
1855 pVCpu->pgm.s.GCPhysNstGstCR3 = NIL_RTGCPHYS;
1856 }
1857
1858#ifdef DEBUG
1859 DBGFR3_INFO_LOG_SAFE(pVM, "mappings", NULL);
1860 DBGFR3_INFO_LOG_SAFE(pVM, "handlers", "all nostat");
1861#endif
1862
1863 /*
1864 * Switch mode back to real mode. (Before resetting the pgm pool!)
1865 */
1866 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1867 {
1868 PVMCPU pVCpu = pVM->apCpusR3[i];
1869
1870 int rc = PGMHCChangeMode(pVM, pVCpu, PGMMODE_REAL);
1871 AssertReleaseRC(rc);
1872
1873 STAM_REL_COUNTER_RESET(&pVCpu->pgm.s.cGuestModeChanges);
1874 STAM_REL_COUNTER_RESET(&pVCpu->pgm.s.cA20Changes);
1875 }
1876
1877 /*
1878 * Reset the shadow page pool.
1879 */
1880 pgmR3PoolReset(pVM);
1881
1882 /*
1883 * Re-init various other members and clear the FFs that PGM owns.
1884 */
1885 for (VMCPUID i = 0; i < pVM->cCpus; i++)
1886 {
1887 PVMCPU pVCpu = pVM->apCpusR3[i];
1888
1889 pVCpu->pgm.s.fGst32BitPageSizeExtension = false;
1890 PGMNotifyNxeChanged(pVCpu, false);
1891
1892 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
1893 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL);
1894
1895 if (!pVCpu->pgm.s.fA20Enabled)
1896 {
1897 pVCpu->pgm.s.fA20Enabled = true;
1898 pVCpu->pgm.s.GCPhysA20Mask = ~((RTGCPHYS)!pVCpu->pgm.s.fA20Enabled << 20);
1899#ifdef PGM_WITH_A20
1900 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
1901 pgmR3RefreshShadowModeAfterA20Change(pVCpu);
1902 HMFlushTlb(pVCpu);
1903#endif
1904 }
1905 }
1906
1907 //pgmLogState(pVM);
1908 PGM_UNLOCK(pVM);
1909}
1910
1911
1912/**
1913 * Memory setup after VM construction or reset.
1914 *
1915 * @param pVM The cross context VM structure.
1916 * @param fAtReset Indicates the context, after reset if @c true or after
1917 * construction if @c false.
1918 */
1919VMMR3_INT_DECL(void) PGMR3MemSetup(PVM pVM, bool fAtReset)
1920{
1921 if (fAtReset)
1922 {
1923 PGM_LOCK_VOID(pVM);
1924
1925 int rc = pgmR3PhysRamZeroAll(pVM);
1926 AssertReleaseRC(rc);
1927
1928 rc = pgmR3PhysRomReset(pVM);
1929 AssertReleaseRC(rc);
1930
1931 PGM_UNLOCK(pVM);
1932 }
1933}
1934
1935
1936#ifdef VBOX_STRICT
1937/**
1938 * VM state change callback for clearing fNoMorePhysWrites after
1939 * a snapshot has been created.
1940 */
1941static DECLCALLBACK(void) pgmR3ResetNoMorePhysWritesFlag(PUVM pUVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser)
1942{
1943 if ( enmState == VMSTATE_RUNNING
1944 || enmState == VMSTATE_RESUMING)
1945 pUVM->pVM->pgm.s.fNoMorePhysWrites = false;
1946 NOREF(enmOldState); NOREF(pvUser);
1947}
1948#endif
1949
1950/**
1951 * Private API to reset fNoMorePhysWrites.
1952 */
1953VMMR3_INT_DECL(void) PGMR3ResetNoMorePhysWritesFlag(PVM pVM)
1954{
1955 pVM->pgm.s.fNoMorePhysWrites = false;
1956}
1957
1958/**
1959 * Terminates the PGM.
1960 *
1961 * @returns VBox status code.
1962 * @param pVM The cross context VM structure.
1963 */
1964VMMR3DECL(int) PGMR3Term(PVM pVM)
1965{
1966 /* Must free shared pages here. */
1967 PGM_LOCK_VOID(pVM);
1968 pgmR3PhysRamTerm(pVM);
1969 pgmR3PhysRomTerm(pVM);
1970 PGM_UNLOCK(pVM);
1971
1972 PGMDeregisterStringFormatTypes();
1973 return PDMR3CritSectDelete(pVM, &pVM->pgm.s.CritSectX);
1974}
1975
1976
1977/**
1978 * Show paging mode.
1979 *
1980 * @param pVM The cross context VM structure.
1981 * @param pHlp The info helpers.
1982 * @param pszArgs "all" (default), "guest", "shadow" or "host".
1983 */
1984static DECLCALLBACK(void) pgmR3InfoMode(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
1985{
1986 /* digest argument. */
1987 bool fGuest, fShadow, fHost;
1988 if (pszArgs)
1989 pszArgs = RTStrStripL(pszArgs);
1990 if (!pszArgs || !*pszArgs || strstr(pszArgs, "all"))
1991 fShadow = fHost = fGuest = true;
1992 else
1993 {
1994 fShadow = fHost = fGuest = false;
1995 if (strstr(pszArgs, "guest"))
1996 fGuest = true;
1997 if (strstr(pszArgs, "shadow"))
1998 fShadow = true;
1999 if (strstr(pszArgs, "host"))
2000 fHost = true;
2001 }
2002
2003 PVMCPU pVCpu = VMMGetCpu(pVM);
2004 if (!pVCpu)
2005 pVCpu = pVM->apCpusR3[0];
2006
2007
2008 /* print info. */
2009 if (fGuest)
2010 {
2011 pHlp->pfnPrintf(pHlp, "Guest paging mode (VCPU #%u): %s (changed %RU64 times), A20 %s (changed %RU64 times)\n",
2012 pVCpu->idCpu, PGMGetModeName(pVCpu->pgm.s.enmGuestMode), pVCpu->pgm.s.cGuestModeChanges.c,
2013 pVCpu->pgm.s.fA20Enabled ? "enabled" : "disabled", pVCpu->pgm.s.cA20Changes.c);
2014#ifdef VBOX_WITH_NESTED_HWVIRT_VMX_EPT
2015 if (pVCpu->pgm.s.enmGuestSlatMode != PGMSLAT_INVALID)
2016 pHlp->pfnPrintf(pHlp, "Guest SLAT mode (VCPU #%u): %s\n", pVCpu->idCpu,
2017 PGMGetSlatModeName(pVCpu->pgm.s.enmGuestSlatMode));
2018#endif
2019 }
2020 if (fShadow)
2021 pHlp->pfnPrintf(pHlp, "Shadow paging mode (VCPU #%u): %s\n", pVCpu->idCpu, PGMGetModeName(pVCpu->pgm.s.enmShadowMode));
2022 if (fHost)
2023 {
2024 const char *psz;
2025 switch (pVM->pgm.s.enmHostMode)
2026 {
2027 case SUPPAGINGMODE_INVALID: psz = "invalid"; break;
2028 case SUPPAGINGMODE_32_BIT: psz = "32-bit"; break;
2029 case SUPPAGINGMODE_32_BIT_GLOBAL: psz = "32-bit+G"; break;
2030 case SUPPAGINGMODE_PAE: psz = "PAE"; break;
2031 case SUPPAGINGMODE_PAE_GLOBAL: psz = "PAE+G"; break;
2032 case SUPPAGINGMODE_PAE_NX: psz = "PAE+NX"; break;
2033 case SUPPAGINGMODE_PAE_GLOBAL_NX: psz = "PAE+G+NX"; break;
2034 case SUPPAGINGMODE_AMD64: psz = "AMD64"; break;
2035 case SUPPAGINGMODE_AMD64_GLOBAL: psz = "AMD64+G"; break;
2036 case SUPPAGINGMODE_AMD64_NX: psz = "AMD64+NX"; break;
2037 case SUPPAGINGMODE_AMD64_GLOBAL_NX: psz = "AMD64+G+NX"; break;
2038 default: psz = "unknown"; break;
2039 }
2040 pHlp->pfnPrintf(pHlp, "Host paging mode: %s\n", psz);
2041 }
2042}
2043
2044
2045/**
2046 * Dump registered MMIO ranges to the log.
2047 *
2048 * @param pVM The cross context VM structure.
2049 * @param pHlp The info helpers.
2050 * @param pszArgs Arguments, ignored.
2051 */
2052static DECLCALLBACK(void) pgmR3PhysInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
2053{
2054 bool const fVerbose = pszArgs && strstr(pszArgs, "verbose") != NULL;
2055
2056 pHlp->pfnPrintf(pHlp,
2057 "RAM ranges (pVM=%p)\n"
2058 "%.*s %.*s\n",
2059 pVM,
2060 sizeof(RTGCPHYS) * 4 + 1, "GC Phys Range ",
2061 sizeof(RTHCPTR) * 2, "pvHC ");
2062
2063 for (PPGMRAMRANGE pCur = pVM->pgm.s.pRamRangesXR3; pCur; pCur = pCur->pNextR3)
2064 {
2065 pHlp->pfnPrintf(pHlp,
2066 "%RGp-%RGp %RHv %s\n",
2067 pCur->GCPhys,
2068 pCur->GCPhysLast,
2069 pCur->pvR3,
2070 pCur->pszDesc);
2071 if (fVerbose)
2072 {
2073 RTGCPHYS const cPages = pCur->cb >> X86_PAGE_SHIFT;
2074 RTGCPHYS iPage = 0;
2075 while (iPage < cPages)
2076 {
2077 RTGCPHYS const iFirstPage = iPage;
2078 PGMPAGETYPE const enmType = (PGMPAGETYPE)PGM_PAGE_GET_TYPE(&pCur->aPages[iPage]);
2079 do
2080 iPage++;
2081 while (iPage < cPages && (PGMPAGETYPE)PGM_PAGE_GET_TYPE(&pCur->aPages[iPage]) == enmType);
2082 const char *pszType;
2083 const char *pszMore = NULL;
2084 switch (enmType)
2085 {
2086 case PGMPAGETYPE_RAM:
2087 pszType = "RAM";
2088 break;
2089
2090 case PGMPAGETYPE_MMIO2:
2091 pszType = "MMIO2";
2092 break;
2093
2094 case PGMPAGETYPE_MMIO2_ALIAS_MMIO:
2095 pszType = "MMIO2-alias-MMIO";
2096 break;
2097
2098 case PGMPAGETYPE_SPECIAL_ALIAS_MMIO:
2099 pszType = "special-alias-MMIO";
2100 break;
2101
2102 case PGMPAGETYPE_ROM_SHADOW:
2103 case PGMPAGETYPE_ROM:
2104 {
2105 pszType = enmType == PGMPAGETYPE_ROM_SHADOW ? "ROM-shadowed" : "ROM";
2106
2107 RTGCPHYS const GCPhysFirstPg = iFirstPage * X86_PAGE_SIZE;
2108 PPGMROMRANGE pRom = pVM->pgm.s.pRomRangesR3;
2109 while (pRom && GCPhysFirstPg > pRom->GCPhysLast)
2110 pRom = pRom->pNextR3;
2111 if (pRom && GCPhysFirstPg - pRom->GCPhys < pRom->cb)
2112 pszMore = pRom->pszDesc;
2113 break;
2114 }
2115
2116 case PGMPAGETYPE_MMIO:
2117 {
2118 pszType = "MMIO";
2119 PGM_LOCK_VOID(pVM);
2120 PPGMPHYSHANDLER pHandler = pgmHandlerPhysicalLookup(pVM, iFirstPage * X86_PAGE_SIZE);
2121 if (pHandler)
2122 pszMore = pHandler->pszDesc;
2123 PGM_UNLOCK(pVM);
2124 break;
2125 }
2126
2127 case PGMPAGETYPE_INVALID:
2128 pszType = "invalid";
2129 break;
2130
2131 default:
2132 pszType = "bad";
2133 break;
2134 }
2135 if (pszMore)
2136 pHlp->pfnPrintf(pHlp, " %RGp-%RGp %-20s %s\n",
2137 pCur->GCPhys + iFirstPage * X86_PAGE_SIZE,
2138 pCur->GCPhys + iPage * X86_PAGE_SIZE - 1,
2139 pszType, pszMore);
2140 else
2141 pHlp->pfnPrintf(pHlp, " %RGp-%RGp %s\n",
2142 pCur->GCPhys + iFirstPage * X86_PAGE_SIZE,
2143 pCur->GCPhys + iPage * X86_PAGE_SIZE - 1,
2144 pszType);
2145
2146 }
2147 }
2148 }
2149}
2150
2151
2152/**
2153 * Dump the page directory to the log.
2154 *
2155 * @param pVM The cross context VM structure.
2156 * @param pHlp The info helpers.
2157 * @param pszArgs Arguments, ignored.
2158 */
2159static DECLCALLBACK(void) pgmR3InfoCr3(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)
2160{
2161 /** @todo SMP support!! */
2162 PVMCPU pVCpu = pVM->apCpusR3[0];
2163
2164/** @todo fix this! Convert the PGMR3DumpHierarchyHC functions to do guest stuff. */
2165 /* Big pages supported? */
2166 const bool fPSE = !!(CPUMGetGuestCR4(pVCpu) & X86_CR4_PSE);
2167
2168 /* Global pages supported? */
2169 const bool fPGE = !!(CPUMGetGuestCR4(pVCpu) & X86_CR4_PGE);
2170
2171 NOREF(pszArgs);
2172
2173 /*
2174 * Get page directory addresses.
2175 */
2176 PGM_LOCK_VOID(pVM);
2177 PX86PD pPDSrc = pgmGstGet32bitPDPtr(pVCpu);
2178 Assert(pPDSrc);
2179
2180 /*
2181 * Iterate the page directory.
2182 */
2183 for (unsigned iPD = 0; iPD < RT_ELEMENTS(pPDSrc->a); iPD++)
2184 {
2185 X86PDE PdeSrc = pPDSrc->a[iPD];
2186 if (PdeSrc.u & X86_PDE_P)
2187 {
2188 if ((PdeSrc.u & X86_PDE_PS) && fPSE)
2189 pHlp->pfnPrintf(pHlp,
2190 "%04X - %RGp P=%d U=%d RW=%d G=%d - BIG\n",
2191 iPD,
2192 pgmGstGet4MBPhysPage(pVM, PdeSrc), PdeSrc.u & X86_PDE_P, !!(PdeSrc.u & X86_PDE_US),
2193 !!(PdeSrc.u & X86_PDE_RW), (PdeSrc.u & X86_PDE4M_G) && fPGE);
2194 else
2195 pHlp->pfnPrintf(pHlp,
2196 "%04X - %RGp P=%d U=%d RW=%d [G=%d]\n",
2197 iPD,
2198 (RTGCPHYS)(PdeSrc.u & X86_PDE_PG_MASK), PdeSrc.u & X86_PDE_P, !!(PdeSrc.u & X86_PDE_US),
2199 !!(PdeSrc.u & X86_PDE_RW), (PdeSrc.u & X86_PDE4M_G) && fPGE);
2200 }
2201 }
2202 PGM_UNLOCK(pVM);
2203}
2204
2205
2206/**
2207 * Called by pgmPoolFlushAllInt prior to flushing the pool.
2208 *
2209 * @returns VBox status code, fully asserted.
2210 * @param pVCpu The cross context virtual CPU structure.
2211 */
2212int pgmR3ExitShadowModeBeforePoolFlush(PVMCPU pVCpu)
2213{
2214 /* Unmap the old CR3 value before flushing everything. */
2215 int rc = VINF_SUCCESS;
2216 uintptr_t idxBth = pVCpu->pgm.s.idxBothModeData;
2217 if ( idxBth < RT_ELEMENTS(g_aPgmBothModeData)
2218 && g_aPgmBothModeData[idxBth].pfnUnmapCR3)
2219 {
2220 rc = g_aPgmBothModeData[idxBth].pfnUnmapCR3(pVCpu);
2221 AssertRC(rc);
2222 }
2223
2224 /* Exit the current shadow paging mode as well; nested paging and EPT use a root CR3 which will get flushed here. */
2225 uintptr_t idxShw = pVCpu->pgm.s.idxShadowModeData;
2226 if ( idxShw < RT_ELEMENTS(g_aPgmShadowModeData)
2227 && g_aPgmShadowModeData[idxShw].pfnExit)
2228 {
2229 rc = g_aPgmShadowModeData[idxShw].pfnExit(pVCpu);
2230 AssertMsgRCReturn(rc, ("Exit failed for shadow mode %d: %Rrc\n", pVCpu->pgm.s.enmShadowMode, rc), rc);
2231 }
2232
2233 Assert(pVCpu->pgm.s.pShwPageCR3R3 == NULL);
2234 return rc;
2235}
2236
2237
2238/**
2239 * Called by pgmPoolFlushAllInt after flushing the pool.
2240 *
2241 * @returns VBox status code, fully asserted.
2242 * @param pVM The cross context VM structure.
2243 * @param pVCpu The cross context virtual CPU structure.
2244 */
2245int pgmR3ReEnterShadowModeAfterPoolFlush(PVM pVM, PVMCPU pVCpu)
2246{
2247 pVCpu->pgm.s.enmShadowMode = PGMMODE_INVALID;
2248 int rc = PGMHCChangeMode(pVM, pVCpu, PGMGetGuestMode(pVCpu));
2249 Assert(VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
2250 AssertRCReturn(rc, rc);
2251 AssertRCSuccessReturn(rc, VERR_IPE_UNEXPECTED_INFO_STATUS);
2252
2253 Assert(pVCpu->pgm.s.pShwPageCR3R3 != NULL || pVCpu->pgm.s.enmShadowMode == PGMMODE_NONE);
2254 AssertMsg( pVCpu->pgm.s.enmShadowMode >= PGMMODE_NESTED_32BIT
2255 || CPUMGetHyperCR3(pVCpu) == PGMGetHyperCR3(pVCpu),
2256 ("%RHp != %RHp %s\n", (RTHCPHYS)CPUMGetHyperCR3(pVCpu), PGMGetHyperCR3(pVCpu), PGMGetModeName(pVCpu->pgm.s.enmShadowMode)));
2257 return rc;
2258}
2259
2260
2261/**
2262 * Called by PGMR3PhysSetA20 after changing the A20 state.
2263 *
2264 * @param pVCpu The cross context virtual CPU structure.
2265 */
2266void pgmR3RefreshShadowModeAfterA20Change(PVMCPU pVCpu)
2267{
2268 /** @todo Probably doing a bit too much here. */
2269 int rc = pgmR3ExitShadowModeBeforePoolFlush(pVCpu);
2270 AssertReleaseRC(rc);
2271 rc = pgmR3ReEnterShadowModeAfterPoolFlush(pVCpu->CTX_SUFF(pVM), pVCpu);
2272 AssertReleaseRC(rc);
2273}
2274
2275
2276#ifdef VBOX_WITH_DEBUGGER
2277
2278/**
2279 * @callback_method_impl{FNDBGCCMD, The '.pgmerror' and '.pgmerroroff' commands.}
2280 */
2281static DECLCALLBACK(int) pgmR3CmdError(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
2282{
2283 /*
2284 * Validate input.
2285 */
2286 DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
2287 PVM pVM = pUVM->pVM;
2288 DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 0, cArgs == 0 || (cArgs == 1 && paArgs[0].enmType == DBGCVAR_TYPE_STRING));
2289
2290 if (!cArgs)
2291 {
2292 /*
2293 * Print the list of error injection locations with status.
2294 */
2295 DBGCCmdHlpPrintf(pCmdHlp, "PGM error inject locations:\n");
2296 DBGCCmdHlpPrintf(pCmdHlp, " handy - %RTbool\n", pVM->pgm.s.fErrInjHandyPages);
2297 }
2298 else
2299 {
2300 /*
2301 * String switch on where to inject the error.
2302 */
2303 bool const fNewState = !strcmp(pCmd->pszCmd, "pgmerror");
2304 const char *pszWhere = paArgs[0].u.pszString;
2305 if (!strcmp(pszWhere, "handy"))
2306 ASMAtomicWriteBool(&pVM->pgm.s.fErrInjHandyPages, fNewState);
2307 else
2308 return DBGCCmdHlpPrintf(pCmdHlp, "error: Invalid 'where' value: %s.\n", pszWhere);
2309 DBGCCmdHlpPrintf(pCmdHlp, "done\n");
2310 }
2311 return VINF_SUCCESS;
2312}
2313
2314
2315/**
2316 * @callback_method_impl{FNDBGCCMD, The '.pgmsync' command.}
2317 */
2318static DECLCALLBACK(int) pgmR3CmdSync(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
2319{
2320 /*
2321 * Validate input.
2322 */
2323 NOREF(pCmd); NOREF(paArgs); NOREF(cArgs);
2324 DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
2325 PVMCPU pVCpu = VMMR3GetCpuByIdU(pUVM, DBGCCmdHlpGetCurrentCpu(pCmdHlp));
2326 if (!pVCpu)
2327 return DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid CPU ID");
2328
2329 /*
2330 * Force page directory sync.
2331 */
2332 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
2333
2334 int rc = DBGCCmdHlpPrintf(pCmdHlp, "Forcing page directory sync.\n");
2335 if (RT_FAILURE(rc))
2336 return rc;
2337
2338 return VINF_SUCCESS;
2339}
2340
2341#ifdef VBOX_STRICT
2342
2343/**
2344 * EMT callback for pgmR3CmdAssertCR3.
2345 *
2346 * @returns VBox status code.
2347 * @param pUVM The user mode VM handle.
2348 * @param pcErrors Where to return the error count.
2349 */
2350static DECLCALLBACK(int) pgmR3CmdAssertCR3EmtWorker(PUVM pUVM, unsigned *pcErrors)
2351{
2352 PVM pVM = pUVM->pVM;
2353 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
2354 PVMCPU pVCpu = VMMGetCpu(pVM);
2355
2356 *pcErrors = PGMAssertCR3(pVM, pVCpu, CPUMGetGuestCR3(pVCpu), CPUMGetGuestCR4(pVCpu));
2357
2358 return VINF_SUCCESS;
2359}
2360
2361
2362/**
2363 * @callback_method_impl{FNDBGCCMD, The '.pgmassertcr3' command.}
2364 */
2365static DECLCALLBACK(int) pgmR3CmdAssertCR3(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
2366{
2367 /*
2368 * Validate input.
2369 */
2370 NOREF(pCmd); NOREF(paArgs); NOREF(cArgs);
2371 DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
2372
2373 int rc = DBGCCmdHlpPrintf(pCmdHlp, "Checking shadow CR3 page tables for consistency.\n");
2374 if (RT_FAILURE(rc))
2375 return rc;
2376
2377 unsigned cErrors = 0;
2378 rc = VMR3ReqCallWaitU(pUVM, DBGCCmdHlpGetCurrentCpu(pCmdHlp), (PFNRT)pgmR3CmdAssertCR3EmtWorker, 2, pUVM, &cErrors);
2379 if (RT_FAILURE(rc))
2380 return DBGCCmdHlpFail(pCmdHlp, pCmd, "VMR3ReqCallWaitU failed: %Rrc", rc);
2381 if (cErrors > 0)
2382 return DBGCCmdHlpFail(pCmdHlp, pCmd, "PGMAssertCR3: %u error(s)", cErrors);
2383 return DBGCCmdHlpPrintf(pCmdHlp, "PGMAssertCR3: OK\n");
2384}
2385
2386#endif /* VBOX_STRICT */
2387
2388/**
2389 * @callback_method_impl{FNDBGCCMD, The '.pgmsyncalways' command.}
2390 */
2391static DECLCALLBACK(int) pgmR3CmdSyncAlways(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
2392{
2393 /*
2394 * Validate input.
2395 */
2396 NOREF(pCmd); NOREF(paArgs); NOREF(cArgs);
2397 DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
2398 PVMCPU pVCpu = VMMR3GetCpuByIdU(pUVM, DBGCCmdHlpGetCurrentCpu(pCmdHlp));
2399 if (!pVCpu)
2400 return DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid CPU ID");
2401
2402 /*
2403 * Force page directory sync.
2404 */
2405 int rc;
2406 if (pVCpu->pgm.s.fSyncFlags & PGM_SYNC_ALWAYS)
2407 {
2408 ASMAtomicAndU32(&pVCpu->pgm.s.fSyncFlags, ~PGM_SYNC_ALWAYS);
2409 rc = DBGCCmdHlpPrintf(pCmdHlp, "Disabled permanent forced page directory syncing.\n");
2410 }
2411 else
2412 {
2413 ASMAtomicOrU32(&pVCpu->pgm.s.fSyncFlags, PGM_SYNC_ALWAYS);
2414 VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
2415 rc = DBGCCmdHlpPrintf(pCmdHlp, "Enabled permanent forced page directory syncing.\n");
2416 }
2417 return rc;
2418}
2419
2420
2421/**
2422 * @callback_method_impl{FNDBGCCMD, The '.pgmphystofile' command.}
2423 */
2424static DECLCALLBACK(int) pgmR3CmdPhysToFile(PCDBGCCMD pCmd, PDBGCCMDHLP pCmdHlp, PUVM pUVM, PCDBGCVAR paArgs, unsigned cArgs)
2425{
2426 /*
2427 * Validate input.
2428 */
2429 NOREF(pCmd);
2430 DBGC_CMDHLP_REQ_UVM_RET(pCmdHlp, pCmd, pUVM);
2431 PVM pVM = pUVM->pVM;
2432 DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 0, cArgs == 1 || cArgs == 2);
2433 DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 0, paArgs[0].enmType == DBGCVAR_TYPE_STRING);
2434 if (cArgs == 2)
2435 {
2436 DBGC_CMDHLP_ASSERT_PARSER_RET(pCmdHlp, pCmd, 1, paArgs[1].enmType == DBGCVAR_TYPE_STRING);
2437 if (strcmp(paArgs[1].u.pszString, "nozero"))
2438 return DBGCCmdHlpFail(pCmdHlp, pCmd, "Invalid 2nd argument '%s', must be 'nozero'.\n", paArgs[1].u.pszString);
2439 }
2440 bool fIncZeroPgs = cArgs < 2;
2441
2442 /*
2443 * Open the output file and get the ram parameters.
2444 */
2445 RTFILE hFile;
2446 int rc = RTFileOpen(&hFile, paArgs[0].u.pszString, RTFILE_O_WRITE | RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE);
2447 if (RT_FAILURE(rc))
2448 return DBGCCmdHlpPrintf(pCmdHlp, "error: RTFileOpen(,'%s',) -> %Rrc.\n", paArgs[0].u.pszString, rc);
2449
2450 uint32_t cbRamHole = 0;
2451 CFGMR3QueryU32Def(CFGMR3GetRootU(pUVM), "RamHoleSize", &cbRamHole, MM_RAM_HOLE_SIZE_DEFAULT);
2452 uint64_t cbRam = 0;
2453 CFGMR3QueryU64Def(CFGMR3GetRootU(pUVM), "RamSize", &cbRam, 0);
2454 RTGCPHYS GCPhysEnd = cbRam + cbRamHole;
2455
2456 /*
2457 * Dump the physical memory, page by page.
2458 */
2459 RTGCPHYS GCPhys = 0;
2460 char abZeroPg[PAGE_SIZE];
2461 RT_ZERO(abZeroPg);
2462
2463 PGM_LOCK_VOID(pVM);
2464 for (PPGMRAMRANGE pRam = pVM->pgm.s.pRamRangesXR3;
2465 pRam && pRam->GCPhys < GCPhysEnd && RT_SUCCESS(rc);
2466 pRam = pRam->pNextR3)
2467 {
2468 /* fill the gap */
2469 if (pRam->GCPhys > GCPhys && fIncZeroPgs)
2470 {
2471 while (pRam->GCPhys > GCPhys && RT_SUCCESS(rc))
2472 {
2473 rc = RTFileWrite(hFile, abZeroPg, PAGE_SIZE, NULL);
2474 GCPhys += PAGE_SIZE;
2475 }
2476 }
2477
2478 PCPGMPAGE pPage = &pRam->aPages[0];
2479 while (GCPhys < pRam->GCPhysLast && RT_SUCCESS(rc))
2480 {
2481 if ( PGM_PAGE_IS_ZERO(pPage)
2482 || PGM_PAGE_IS_BALLOONED(pPage))
2483 {
2484 if (fIncZeroPgs)
2485 {
2486 rc = RTFileWrite(hFile, abZeroPg, PAGE_SIZE, NULL);
2487 if (RT_FAILURE(rc))
2488 DBGCCmdHlpPrintf(pCmdHlp, "error: RTFileWrite -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
2489 }
2490 }
2491 else
2492 {
2493 switch (PGM_PAGE_GET_TYPE(pPage))
2494 {
2495 case PGMPAGETYPE_RAM:
2496 case PGMPAGETYPE_ROM_SHADOW: /* trouble?? */
2497 case PGMPAGETYPE_ROM:
2498 case PGMPAGETYPE_MMIO2:
2499 {
2500 void const *pvPage;
2501 PGMPAGEMAPLOCK Lock;
2502 rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, GCPhys, &pvPage, &Lock);
2503 if (RT_SUCCESS(rc))
2504 {
2505 rc = RTFileWrite(hFile, pvPage, PAGE_SIZE, NULL);
2506 PGMPhysReleasePageMappingLock(pVM, &Lock);
2507 if (RT_FAILURE(rc))
2508 DBGCCmdHlpPrintf(pCmdHlp, "error: RTFileWrite -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
2509 }
2510 else
2511 DBGCCmdHlpPrintf(pCmdHlp, "error: PGMPhysGCPhys2CCPtrReadOnly -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
2512 break;
2513 }
2514
2515 default:
2516 AssertFailed();
2517 RT_FALL_THRU();
2518 case PGMPAGETYPE_MMIO:
2519 case PGMPAGETYPE_MMIO2_ALIAS_MMIO:
2520 case PGMPAGETYPE_SPECIAL_ALIAS_MMIO:
2521 if (fIncZeroPgs)
2522 {
2523 rc = RTFileWrite(hFile, abZeroPg, PAGE_SIZE, NULL);
2524 if (RT_FAILURE(rc))
2525 DBGCCmdHlpPrintf(pCmdHlp, "error: RTFileWrite -> %Rrc at GCPhys=%RGp.\n", rc, GCPhys);
2526 }
2527 break;
2528 }
2529 }
2530
2531
2532 /* advance */
2533 GCPhys += PAGE_SIZE;
2534 pPage++;
2535 }
2536 }
2537 PGM_UNLOCK(pVM);
2538
2539 RTFileClose(hFile);
2540 if (RT_SUCCESS(rc))
2541 return DBGCCmdHlpPrintf(pCmdHlp, "Successfully saved physical memory to '%s'.\n", paArgs[0].u.pszString);
2542 return VINF_SUCCESS;
2543}
2544
2545#endif /* VBOX_WITH_DEBUGGER */
2546
2547/**
2548 * pvUser argument of the pgmR3CheckIntegrity*Node callbacks.
2549 */
2550typedef struct PGMCHECKINTARGS
2551{
2552 bool fLeftToRight; /**< true: left-to-right; false: right-to-left. */
2553 PPGMPHYSHANDLER pPrevPhys;
2554 PVM pVM;
2555} PGMCHECKINTARGS, *PPGMCHECKINTARGS;
2556
2557/**
2558 * Validate a node in the physical handler tree.
2559 *
2560 * @returns 0 on if ok, other wise 1.
2561 * @param pNode The handler node.
2562 * @param pvUser pVM.
2563 */
2564static DECLCALLBACK(int) pgmR3CheckIntegrityPhysHandlerNode(PAVLROGCPHYSNODECORE pNode, void *pvUser)
2565{
2566 PPGMCHECKINTARGS pArgs = (PPGMCHECKINTARGS)pvUser;
2567 PPGMPHYSHANDLER pCur = (PPGMPHYSHANDLER)pNode;
2568 AssertReleaseReturn(!((uintptr_t)pCur & 7), 1);
2569 AssertReleaseMsg(pCur->Core.Key <= pCur->Core.KeyLast,
2570 ("pCur=%p %RGp-%RGp %s\n", pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc));
2571 AssertReleaseMsg( !pArgs->pPrevPhys
2572 || ( pArgs->fLeftToRight
2573 ? pArgs->pPrevPhys->Core.KeyLast < pCur->Core.Key
2574 : pArgs->pPrevPhys->Core.KeyLast > pCur->Core.Key),
2575 ("pPrevPhys=%p %RGp-%RGp %s\n"
2576 " pCur=%p %RGp-%RGp %s\n",
2577 pArgs->pPrevPhys, pArgs->pPrevPhys->Core.Key, pArgs->pPrevPhys->Core.KeyLast, pArgs->pPrevPhys->pszDesc,
2578 pCur, pCur->Core.Key, pCur->Core.KeyLast, pCur->pszDesc));
2579 pArgs->pPrevPhys = pCur;
2580 return 0;
2581}
2582
2583
2584/**
2585 * Perform an integrity check on the PGM component.
2586 *
2587 * @returns VINF_SUCCESS if everything is fine.
2588 * @returns VBox error status after asserting on integrity breach.
2589 * @param pVM The cross context VM structure.
2590 */
2591VMMR3DECL(int) PGMR3CheckIntegrity(PVM pVM)
2592{
2593 /*
2594 * Check the trees.
2595 */
2596 int cErrors = 0;
2597 const PGMCHECKINTARGS LeftToRight = { true, NULL, pVM };
2598 const PGMCHECKINTARGS RightToLeft = { false, NULL, pVM };
2599 PGMCHECKINTARGS Args = LeftToRight;
2600 cErrors += RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesR3->PhysHandlers, true, pgmR3CheckIntegrityPhysHandlerNode, &Args);
2601 Args = RightToLeft;
2602 cErrors += RTAvlroGCPhysDoWithAll(&pVM->pgm.s.pTreesR3->PhysHandlers, false, pgmR3CheckIntegrityPhysHandlerNode, &Args);
2603
2604 return !cErrors ? VINF_SUCCESS : VERR_INTERNAL_ERROR;
2605}
2606
Note: See TracBrowser for help on using the repository browser.

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