VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/PGMR0SharedPage.cpp@ 38816

Last change on this file since 38816 was 37354, checked in by vboxsync, 14 years ago

PGM: Fixed locking issues in PGMR3PhysMMIORegister and PGMR3PhysMMIODeregister. Also addressed a harmless on in PGMR3PhysRomRegister (only used at init time, so no races). Fortified the code with assertions more lock assertion, replacing the incorrect PGMIsLocked() checks (we only care if the current thread is the lock owner). Cleaned up some ReturnStmt macros and adding more of them.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 6.2 KB
Line 
1/* $Id: PGMR0SharedPage.cpp 37354 2011-06-07 15:05:32Z vboxsync $ */
2/** @file
3 * PGM - Page Manager and Monitor, Page Sharing, Ring-0.
4 */
5
6/*
7 * Copyright (C) 2010 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* Header Files *
20*******************************************************************************/
21#define LOG_GROUP LOG_GROUP_PGM_SHARED
22#include <VBox/vmm/pgm.h>
23#include <VBox/vmm/gmm.h>
24#include "PGMInternal.h"
25#include <VBox/vmm/vm.h>
26#include "PGMInline.h"
27#include <VBox/log.h>
28#include <VBox/err.h>
29#include <iprt/assert.h>
30#include <iprt/mem.h>
31
32
33#ifdef VBOX_WITH_PAGE_SHARING
34/**
35 * Check a registered module for shared page changes
36 *
37 * @returns The following VBox status codes.
38 *
39 * @param pVM The VM handle.
40 * @param pGVM Pointer to the GVM instance data.
41 * @param idCpu VCPU id
42 * @param pModule Module description
43 * @param cRegions Number of regions
44 * @param pRegions Region array
45 */
46VMMR0DECL(int) PGMR0SharedModuleCheck(PVM pVM, PGVM pGVM, VMCPUID idCpu, PGMMSHAREDMODULE pModule, uint32_t cRegions, PGMMSHAREDREGIONDESC pRegions)
47{
48 int rc = VINF_SUCCESS;
49 GMMSHAREDPAGEDESC PageDesc;
50 bool fFlushTLBs = false;
51 PVMCPU pVCpu = &pVM->aCpus[idCpu];
52
53 Log(("PGMR0SharedModuleCheck: check %s %s base=%RGv size=%x\n", pModule->szName, pModule->szVersion, pModule->Core.Key, pModule->cbModule));
54
55 PGM_LOCK_ASSERT_OWNER(pVM); /* This cannot fail as we grab the lock in pgmR3SharedModuleRegRendezvous before calling into ring-0. */
56
57 /* Check every region of the shared module. */
58 for (unsigned idxRegion = 0; idxRegion < cRegions; idxRegion++)
59 {
60 Assert((pRegions[idxRegion].cbRegion & 0xfff) == 0);
61 Assert((pRegions[idxRegion].GCRegionAddr & 0xfff) == 0);
62
63 RTGCPTR GCRegion = pRegions[idxRegion].GCRegionAddr;
64 unsigned cbRegion = pRegions[idxRegion].cbRegion & ~0xfff;
65 unsigned idxPage = 0;
66
67 while (cbRegion)
68 {
69 RTGCPHYS GCPhys;
70 uint64_t fFlags;
71
72 /** @todo inefficient to fetch each guest page like this... */
73 rc = PGMGstGetPage(pVCpu, GCRegion, &fFlags, &GCPhys);
74 if ( rc == VINF_SUCCESS
75 && !(fFlags & X86_PTE_RW)) /* important as we make assumptions about this below! */
76 {
77 PPGMPAGE pPage = pgmPhysGetPage(pVM, GCPhys);
78 Assert(!pPage || !PGM_PAGE_IS_BALLOONED(pPage));
79 if ( pPage
80 && PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED)
81 {
82 PageDesc.uHCPhysPageId = PGM_PAGE_GET_PAGEID(pPage);
83 PageDesc.HCPhys = PGM_PAGE_GET_HCPHYS(pPage);
84 PageDesc.GCPhys = GCPhys;
85
86 rc = GMMR0SharedModuleCheckPage(pGVM, pModule, idxRegion, idxPage, &PageDesc);
87 if (rc == VINF_SUCCESS)
88 {
89 /* Any change for this page? */
90 if (PageDesc.uHCPhysPageId != NIL_GMM_PAGEID)
91 {
92 Assert(PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED);
93
94 Log(("PGMR0SharedModuleCheck: shared page gc virt=%RGv phys %RGp host %RHp->%RHp\n", pRegions[idxRegion].GCRegionAddr + idxPage * PAGE_SIZE, PageDesc.GCPhys, PGM_PAGE_GET_HCPHYS(pPage), PageDesc.HCPhys));
95 if (PageDesc.HCPhys != PGM_PAGE_GET_HCPHYS(pPage))
96 {
97 bool fFlush = false;
98
99 /* Page was replaced by an existing shared version of it; clear all references first. */
100 rc = pgmPoolTrackUpdateGCPhys(pVM, PageDesc.GCPhys, pPage, true /* clear the entries */, &fFlush);
101 Assert(rc == VINF_SUCCESS || (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_PGM_SYNC_CR3) && (pVCpu->pgm.s.fSyncFlags & PGM_SYNC_CLEAR_PGM_POOL)));
102 if (rc == VINF_SUCCESS)
103 fFlushTLBs |= fFlush;
104
105 /* Update the physical address and page id now. */
106 PGM_PAGE_SET_HCPHYS(pVM, pPage, PageDesc.HCPhys);
107 PGM_PAGE_SET_PAGEID(pVM, pPage, PageDesc.uHCPhysPageId);
108
109 /* Invalidate page map TLB entry for this page too. */
110 pgmPhysInvalidatePageMapTLBEntry(pVM, PageDesc.GCPhys);
111 pVM->pgm.s.cReusedSharedPages++;
112 }
113 /* else nothing changed (== this page is now a shared page), so no need to flush anything. */
114
115 pVM->pgm.s.cSharedPages++;
116 pVM->pgm.s.cPrivatePages--;
117 PGM_PAGE_SET_STATE(pVM, pPage, PGM_PAGE_STATE_SHARED);
118 }
119 }
120 else
121 break;
122 }
123 }
124 else
125 {
126 Assert( rc == VINF_SUCCESS
127 || rc == VERR_PAGE_NOT_PRESENT
128 || rc == VERR_PAGE_MAP_LEVEL4_NOT_PRESENT
129 || rc == VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT
130 || rc == VERR_PAGE_TABLE_NOT_PRESENT);
131 rc = VINF_SUCCESS; /* ignore error */
132 }
133
134 idxPage++;
135 GCRegion += PAGE_SIZE;
136 cbRegion -= PAGE_SIZE;
137 }
138 }
139
140 if (fFlushTLBs)
141 PGM_INVL_ALL_VCPU_TLBS(pVM);
142
143 return rc;
144}
145#endif /* VBOX_WITH_PAGE_SHARING */
146
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