7
* Copyright (C) 2006-2010 Oracle Corporation
7
* Copyright (C) 2006-2012 Oracle Corporation
9
9
* This file is part of VirtualBox Open Source Edition (OSE), as
10
10
* available from http://www.virtualbox.org. This file is free software;
106
106
* world switch overhead, so let's sync more.
109
/* Chose 32 based on the compile test in #4219; 64 shows worse stats.
109
/* Chose 32 based on the compile test in @bugref{4219}; 64 shows worse stats.
110
110
* 32 again shows better results than 16; slightly more overhead in the \#PF handler,
111
111
* but ~5% fewer faults.
220
220
* Maps a HC physical page pool address to a virtual address.
222
222
* @returns VBox status code.
223
* @param pVM The VM handle.
223
* @param pVM Pointer to the VM.
224
224
* @param pVCpu The current CPU.
225
225
* @param HCPhys The HC physical address to map to a virtual one.
226
226
* @param ppv Where to store the virtual address. No need to cast
242
242
* Maps a GC physical page address to a virtual address.
244
244
* @returns VBox status code.
245
* @param pVM The VM handle.
245
* @param pVM Pointer to the VM.
246
246
* @param pVCpu The current CPU.
247
247
* @param GCPhys The GC physical address to map to a virtual one.
248
248
* @param ppv Where to store the virtual address. No need to cast this.
263
263
* Maps a GC physical page address to a virtual address.
265
265
* @returns VBox status code.
266
* @param pVM The VM handle.
266
* @param pVM Pointer to the VM.
267
267
* @param GCPhys The GC physical address to map to a virtual one.
268
268
* @param ppv Where to store the virtual address. No need to cast this.
291
291
* Maps a unaligned GC physical page address to a virtual address.
293
293
* @returns VBox status code.
294
* @param pVM The VM handle.
294
* @param pVM Pointer to the VM.
295
295
* @param GCPhys The GC physical address to map to a virtual one.
296
296
* @param ppv Where to store the virtual address. No need to cast this.
333
333
* For best effect only apply this to the page that was mapped most recently.
335
* @param pVM The VM handle.
335
* @param pVM Pointer to the VM.
336
336
* @param pvPage The pool page.
338
338
#define PGM_DYNMAP_UNUSED_HINT_VM(pVM, pvPage) PGM_DYNMAP_UNUSED_HINT(VMMGetCpu(pVM), pvPage)
355
355
/** @def PGM_INVL_PG_ALL_VCPU
356
356
* Invalidates a page on all VCPUs
358
* @param pVM The VM handle.
358
* @param pVM Pointer to the VM.
359
359
* @param GCVirt The virtual address of the page to invalidate.
383
383
/** @def PGM_INVL_VCPU_TLBS()
384
384
* Invalidates the TLBs of the specified VCPU
386
* @param pVCpu The VMCPU handle.
386
* @param pVCpu Pointer to the VMCPU.
389
389
# define PGM_INVL_VCPU_TLBS(pVCpu) ASMReloadCR3()
396
396
/** @def PGM_INVL_ALL_VCPU_TLBS()
397
397
* Invalidates the TLBs of all VCPUs
399
* @param pVM The VM handle.
399
* @param pVM Pointer to the VM.
402
402
# define PGM_INVL_ALL_VCPU_TLBS(pVM) ASMReloadCR3()
2065
2065
/** Shw: 64-bit page directory table; Gst: 64-bit page directory table. */
2066
2066
PGMPOOLKIND_64BIT_PD_FOR_64BIT_PD,
2067
2067
/** Shw: 64-bit page directory table; Gst: no paging */
2068
PGMPOOLKIND_64BIT_PD_FOR_PHYS, /* 22 */
2068
PGMPOOLKIND_64BIT_PD_FOR_PHYS, /* 24 */
2070
2070
/** Shw: 64-bit PML4; Gst: 64-bit PML4. */
2071
2071
PGMPOOLKIND_64BIT_PML4,
2106
2106
typedef struct PGMPOOLPAGE
2108
/** AVL node code with the (R3) physical address of this page. */
2108
/** AVL node code with the (HC) physical address of this page. */
2109
2109
AVLOHCPHYSNODECORE Core;
2110
2110
/** Pointer to the R3 mapping of the page. */
2111
2111
#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
2114
2114
R3R0PTRTYPE(void *) pvPageR3;
2116
/** The guest physical address. */
2117
2116
#if HC_ARCH_BITS == 32 && GC_ARCH_BITS == 64
2118
2117
uint32_t Alignment0;
2119
/** The guest physical address. */
2120
2120
RTGCPHYS GCPhys;
2122
/** Access handler statistics to determine whether the guest is (re)initializing a page table. */
2123
RTGCPTR pvLastAccessHandlerRip;
2124
RTGCPTR pvLastAccessHandlerFault;
2125
uint64_t cLastAccessHandlerCount;
2127
2121
/** The kind of page we're shadowing. (This is really a PGMPOOLKIND enum.) */
2128
2122
uint8_t enmKind;
2129
2123
/** The subkind of page we're shadowing. (This is really a PGMPOOLACCESS enum.) */
2130
2124
uint8_t enmAccess;
2125
/** This supplements enmKind and enmAccess */
2126
bool fA20Enabled : 1;
2128
/** Used to indicate that the page is zeroed. */
2130
/** Used to indicate that a PT has non-global entries. */
2131
bool fSeenNonGlobal : 1;
2132
/** Used to indicate that we're monitoring writes to the guest page. */
2133
bool fMonitored : 1;
2134
/** Used to indicate that the page is in the cache (e.g. in the GCPhys hash).
2135
* (All pages are in the age list.) */
2137
/** This is used by the R3 access handlers when invoked by an async thread.
2138
* It's a hack required because of REMR3NotifyHandlerPhysicalDeregister. */
2139
bool volatile fReusedFlushPending : 1;
2140
/** Used to mark the page as dirty (write monitoring is temporarily
2131
2146
/** The index of this page. */
2133
2148
/** The next entry in the list this page currently resides in.
2153
2168
uint16_t iAgeNext;
2154
2169
/** The previous page in the age list. */
2155
2170
uint16_t iAgePrev;
2156
/** Used to indicate that the page is zeroed. */
2158
/** Used to indicate that a PT has non-global entries. */
2159
bool fSeenNonGlobal;
2160
/** Used to indicate that we're monitoring writes to the guest page. */
2162
/** Used to indicate that the page is in the cache (e.g. in the GCPhys hash).
2163
* (All pages are in the age list.) */
2165
/** This is used by the R3 access handlers when invoked by an async thread.
2166
* It's a hack required because of REMR3NotifyHandlerPhysicalDeregister. */
2167
bool volatile fReusedFlushPending;
2168
/** Used to mark the page as dirty (write monitoring is temporarily
2171
/** Index into PGMPOOL::aDirtyPages if fDirty is set. */
2172
uint8_t idxDirtyEntry;
2172
/** Used to indicate that this page can't be flushed. Important for cr3 root pages or shadow pae pd pages). */
2175
RTGCPTR pvDirtyFault;
2176
} PGMPOOLPAGE, *PPGMPOOLPAGE, **PPPGMPOOLPAGE;
2174
/** @name Access handler statistics to determine whether the guest is
2175
* (re)initializing a page table.
2177
RTGCPTR GCPtrLastAccessHandlerRip;
2178
RTGCPTR GCPtrLastAccessHandlerFault;
2179
uint64_t cLastAccessHandler;
2181
/** Used to indicate that this page can't be flushed. Important for cr3 root pages or shadow pae pd pages. */
2182
uint32_t volatile cLocked;
2183
#if GC_ARCH_BITS == 64
2184
uint32_t u32Alignment3;
2187
RTGCPTR GCPtrDirtyFault;
2190
/** Pointer to a pool page. */
2191
typedef PGMPOOLPAGE *PPGMPOOLPAGE;
2177
2192
/** Pointer to a const pool page. */
2178
2193
typedef PGMPOOLPAGE const *PCPGMPOOLPAGE;
2194
/** Pointer to a pool page pointer. */
2195
typedef PGMPOOLPAGE **PPPGMPOOLPAGE;
2181
2198
/** The hash table size. */
2255
2272
/** Alignment padding. */
2256
2273
uint32_t u32Padding2;
2258
/* Next available slot. */
2275
/** Next available slot (in aDirtyPages). */
2259
2276
uint32_t idxFreeDirtyPage;
2260
/* Number of active dirty pages. */
2277
/** Number of active dirty pages. */
2261
2278
uint32_t cDirtyPages;
2262
/* Array of current dirty pgm pool page indices. */
2279
/** Array of current dirty pgm pool page indices. */
2418
2435
* Maps a pool page pool into the current context.
2420
2437
* @returns VBox status code.
2421
* @param a_pVM The VM handle.
2438
* @param a_pVM Pointer to the VM.
2422
2439
* @param a_pPage The pool page.
2424
2441
* @remark In RC this uses PGMGCDynMapHCPage(), so it will consume of the
2428
2445
#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
2429
2446
# define PGMPOOL_PAGE_2_PTR(a_pVM, a_pPage) pgmPoolMapPageInlined((a_pVM), (a_pPage) RTLOG_COMMA_SRC_POS)
2430
#elif defined(VBOX_STRICT)
2431
# define PGMPOOL_PAGE_2_PTR(a_pVM, a_pPage) pgmPoolMapPageStrict(a_pPage)
2432
DECLINLINE(void *) pgmPoolMapPageStrict(PPGMPOOLPAGE a_pPage)
2447
#elif defined(VBOX_STRICT) || 1 /* temporarily going strict here */
2448
# define PGMPOOL_PAGE_2_PTR(a_pVM, a_pPage) pgmPoolMapPageStrict(a_pPage, __FUNCTION__)
2449
DECLINLINE(void *) pgmPoolMapPageStrict(PPGMPOOLPAGE a_pPage, const char *pszCaller)
2434
Assert(a_pPage && a_pPage->pvPageR3);
2452
AssertReleaseMsg(RT_VALID_PTR(a_pPage->pvPageR3), ("enmKind=%d idx=%#x HCPhys=%RHp GCPhys=%RGp caller=%s\n", a_pPage->enmKind, a_pPage->idx, a_pPage->Core.Key, a_pPage->GCPhys, pszCaller));
2435
2453
return a_pPage->pvPageR3;
2443
2461
* Maps a pool page pool into the current context, taking both VM and VMCPU.
2445
2463
* @returns VBox status code.
2446
* @param a_pVM The VM handle.
2464
* @param a_pVM Pointer to the VM.
2447
2465
* @param a_pVCpu The current CPU.
2448
2466
* @param a_pPage The pool page.
2541
/** @name A20 gate macros
2543
#define PGM_WITH_A20
2545
# define PGM_A20_IS_ENABLED(a_pVCpu) ((a_pVCpu)->pgm.s.fA20Enabled)
2546
# define PGM_A20_APPLY(a_pVCpu, a_GCPhys) ((a_GCPhys) & (a_pVCpu)->pgm.s.GCPhysA20Mask)
2547
# define PGM_A20_APPLY_TO_VAR(a_pVCpu, a_GCPhysVar) \
2548
do { a_GCPhysVar &= (a_pVCpu)->pgm.s.GCPhysA20Mask; } while (0)
2549
# define PGM_A20_ASSERT_MASKED(pVCpu, a_GCPhys) Assert(PGM_A20_APPLY(pVCpu, a_GCPhys) == (a_GCPhys))
2551
# define PGM_A20_IS_ENABLED(a_pVCpu) (true)
2552
# define PGM_A20_APPLY(a_pVCpu, a_GCPhys) (a_GCPhys)
2553
# define PGM_A20_APPLY_TO_VAR(a_pVCpu, a_GCPhysVar) do { } while (0)
2554
# define PGM_A20_ASSERT_MASKED(pVCpu, a_GCPhys) do { } while (0)
2523
2560
* Trees are using self relative offsets as pointers.
2524
2561
* So, all its data, including the root pointer, must be in the heap for HC and GC
3712
3749
R0PTRTYPE(PPGMPOOLPAGE) pShwPageCR3R0;
3713
3750
/** Pointer to the page of the current active CR3 - RC Ptr. */
3714
3751
RCPTRTYPE(PPGMPOOLPAGE) pShwPageCR3RC;
3715
/* The shadow page pool index of the user table as specified during allocation; useful for freeing root pages */
3752
/** The shadow page pool index of the user table as specified during
3753
* allocation; useful for freeing root pages. */
3716
3754
uint32_t iShwUser;
3717
/* The index into the user table (shadowed) as specified during allocation; useful for freeing root pages. */
3755
/** The index into the user table (shadowed) as specified during allocation;
3756
* useful for freeing root pages. */
3718
3757
uint32_t iShwUserTable;
3719
3758
# if HC_ARCH_BITS == 64
3720
3759
RTRCPTR alignment6; /**< structure size alignment. */
3795
3834
/** For saving stack space, the disassembler state is allocated here instead of
3797
* @note The DISCPUSTATE structure is not R3/R0/RZ clean! */
3800
/** The disassembler scratch space. */
3801
DISCPUSTATE DisState;
3803
uint8_t abDisStatePadding[DISCPUSTATE_PADDING_SIZE];
3836
DISCPUSTATE DisState;
3806
3838
/** Count the number of pgm pool access handler calls. */
3807
3839
uint64_t cPoolAccessHandler;
3811
3843
/** The number of times the guest has switched mode since last reset or statistics reset. */
3812
3844
STAMCOUNTER cGuestModeChanges;
3845
/** The number of times the guest has switched mode since last reset or statistics reset. */
3846
STAMCOUNTER cA20Changes;
3815
3849
#ifdef VBOX_WITH_STATISTICS /** @todo move this chunk to the heap. */
3860
3894
* Asserts that the caller owns the PDM lock.
3861
3895
* This is the internal variant of PGMIsLockOwner.
3862
* @param a_pVM The VM handle.
3896
* @param a_pVM Pointer to the VM.
3864
3898
#define PGM_LOCK_ASSERT_OWNER(a_pVM) Assert(PDMCritSectIsOwner(&(a_pVM)->pgm.s.CritSectX))
3866
3900
* Asserts that the caller owns the PDM lock.
3867
3901
* This is the internal variant of PGMIsLockOwner.
3868
* @param a_pVM The VM handle.
3902
* @param a_pVM Pointer to the VM.
3869
3903
* @param a_pVCpu The current CPU handle.
3871
3905
#define PGM_LOCK_ASSERT_OWNER_EX(a_pVM, a_pVCpu) Assert(PDMCritSectIsOwnerEx(&(a_pVM)->pgm.s.CritSectX, pVCpu))
3907
#ifndef PGM_WITHOUT_MAPPINGS
3873
3908
int pgmR3MappingsFixInternal(PVM pVM, RTGCPTR GCPtrBase, uint32_t cb);
3874
3909
int pgmR3SyncPTResolveConflict(PVM pVM, PPGMMAPPING pMapping, PX86PD pPDSrc, RTGCPTR GCPtrOldMapping);
3875
3910
int pgmR3SyncPTResolveConflictPAE(PVM pVM, PPGMMAPPING pMapping, RTGCPTR GCPtrOldMapping);
3911
int pgmMapResolveConflicts(PVM pVM);
3912
#endif /* !PGM_WITHOUT_MAPPINGS */
3876
3913
PPGMMAPPING pgmGetMapping(PVM pVM, RTGCPTR GCPtr);
3877
int pgmMapResolveConflicts(PVM pVM);
3878
3914
DECLCALLBACK(void) pgmR3MapInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
3880
3916
void pgmR3HandlerPhysicalUpdateAll(PVM pVM);
3902
3938
int pgmPhysPageMapReadOnly(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, void const **ppv);
3903
3939
int pgmPhysPageMapByPageID(PVM pVM, uint32_t idPage, RTHCPHYS HCPhys, void **ppv);
3904
3940
int pgmPhysGCPhys2R3Ptr(PVM pVM, RTGCPHYS GCPhys, PRTR3PTR pR3Ptr);
3941
int pgmPhysCr3ToHCPtr(PVM pVM, RTGCPHYS GCPhys, PRTR3PTR pR3Ptr);
3905
3942
int pgmPhysGCPhys2CCPtrInternalDepr(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, void **ppv);
3906
3943
int pgmPhysGCPhys2CCPtrInternal(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, void **ppv, PPGMPAGEMAPLOCK pLock);
3907
3944
int pgmPhysGCPhys2CCPtrInternalReadOnly(PVM pVM, PPGMPAGE pPage, RTGCPHYS GCPhys, const void **ppv, PPGMPAGEMAPLOCK pLock);
3926
3963
int pgmR3PhysChunkMap(PVM pVM, uint32_t idChunk, PPPGMCHUNKR3MAP ppChunk);
3927
3964
int pgmR3PhysRamTerm(PVM pVM);
3928
3965
void pgmR3PhysRomTerm(PVM pVM);
3966
void pgmR3PhysAssertSharedPageChecksums(PVM pVM);
3930
3968
int pgmR3PoolInit(PVM pVM);
3931
3969
void pgmR3PoolRelocate(PVM pVM);
3945
3983
void pgmRZDynMapUnusedHint(PVMCPU pVCpu, void *pvHint);
3948
int pgmPoolAllocEx(PVM pVM, RTGCPHYS GCPhys, PGMPOOLKIND enmKind, PGMPOOLACCESS enmAccess, uint16_t iUser,
3949
uint32_t iUserTable, bool fLockPage, PPPGMPOOLPAGE ppPage);
3951
DECLINLINE(int) pgmPoolAlloc(PVM pVM, RTGCPHYS GCPhys, PGMPOOLKIND enmKind, uint16_t iUser, uint32_t iUserTable,
3952
PPPGMPOOLPAGE ppPage)
3954
return pgmPoolAllocEx(pVM, GCPhys, enmKind, PGMPOOLACCESS_DONTCARE, iUser, iUserTable, false, ppPage);
3986
int pgmPoolAlloc(PVM pVM, RTGCPHYS GCPhys, PGMPOOLKIND enmKind, PGMPOOLACCESS enmAccess, bool fA20Enabled,
3987
uint16_t iUser, uint32_t iUserTable, bool fLockPage, PPPGMPOOLPAGE ppPage);
3957
3988
void pgmPoolFree(PVM pVM, RTHCPHYS HCPhys, uint16_t iUser, uint32_t iUserTable);
3958
3989
void pgmPoolFreeByPage(PPGMPOOL pPool, PPGMPOOLPAGE pPage, uint16_t iUser, uint32_t iUserTable);
3959
3990
int pgmPoolFlushPage(PPGMPOOL pPool, PPGMPOOLPAGE pPage, bool fFlush = true /* DO NOT USE false UNLESS YOU KNOWN WHAT YOU'RE DOING!! */);
3975
4006
void pgmPoolResetDirtyPages(PVM pVM);
3976
4007
void pgmPoolResetDirtyPage(PVM pVM, RTGCPTR GCPtrPage);
3978
int pgmR3ExitShadowModeBeforePoolFlush(PVM pVM, PVMCPU pVCpu);
4009
int pgmR3ExitShadowModeBeforePoolFlush(PVMCPU pVCpu);
3979
4010
int pgmR3ReEnterShadowModeAfterPoolFlush(PVM pVM, PVMCPU pVCpu);
4011
void pgmR3RefreshShadowModeAfterA20Change(PVMCPU pVCpu);
3981
4013
void pgmMapSetShadowPDEs(PVM pVM, PPGMMAPPING pMap, unsigned iNewPDE);
3982
4014
void pgmMapClearShadowPDEs(PVM pVM, PPGMPOOLPAGE pShwPageCR3, PPGMMAPPING pMap, unsigned iOldPDE, bool fDeactivateCR3);