VirtualBox

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

Last change on this file since 93705 was 93554, checked in by vboxsync, 3 years ago

VMM: Changed PAGE_SIZE -> GUEST_PAGE_SIZE / HOST_PAGE_SIZE, PAGE_SHIFT -> GUEST_PAGE_SHIFT / HOST_PAGE_SHIFT, and PAGE_OFFSET_MASK -> GUEST_PAGE_OFFSET_MASK / HOST_PAGE_OFFSET_MASK. Also removed most usage of ASMMemIsZeroPage and ASMMemZeroPage since the host and guest page size doesn't need to be the same any more. Some work left to do in the page pool code. bugref:9898

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 7.3 KB
Line 
1/* $Id: PGMR0SharedPage.cpp 93554 2022-02-02 22:57:02Z vboxsync $ */
2/** @file
3 * PGM - Page Manager and Monitor, Page Sharing, Ring-0.
4 */
5
6/*
7 * Copyright (C) 2010-2022 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/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_PGM_SHARED
23#define VBOX_WITHOUT_PAGING_BIT_FIELDS /* 64-bit bitfields are just asking for trouble. See @bugref{9841} and others. */
24#include <VBox/vmm/pgm.h>
25#include <VBox/vmm/gmm.h>
26#include "PGMInternal.h"
27#include <VBox/vmm/vmcc.h>
28#include <VBox/vmm/gvm.h>
29#include "PGMInline.h"
30#include <VBox/log.h>
31#include <VBox/err.h>
32#include <iprt/assert.h>
33#include <iprt/mem.h>
34
35
36#ifdef VBOX_WITH_PAGE_SHARING
37/**
38 * Check a registered module for shared page changes.
39 *
40 * The PGM lock shall be taken prior to calling this method.
41 *
42 * @returns The following VBox status codes.
43 *
44 * @param pVM The cross context VM structure.
45 * @param pGVM Pointer to the GVM instance data.
46 * @param idCpu The ID of the calling virtual CPU.
47 * @param pModule Global module description.
48 * @param paRegionsGCPtrs Array parallel to pModules->aRegions with the
49 * addresses of the regions in the calling
50 * process.
51 */
52VMMR0DECL(int) PGMR0SharedModuleCheck(PVMCC pVM, PGVM pGVM, VMCPUID idCpu, PGMMSHAREDMODULE pModule, PCRTGCPTR64 paRegionsGCPtrs)
53{
54 PVMCPUCC pVCpu = &pGVM->aCpus[idCpu];
55 int rc = VINF_SUCCESS;
56 bool fFlushTLBs = false;
57 bool fFlushRemTLBs = false;
58 GMMSHAREDPAGEDESC PageDesc;
59
60 Log(("PGMR0SharedModuleCheck: check %s %s base=%RGv size=%x\n", pModule->szName, pModule->szVersion, pModule->Core.Key, pModule->cbModule));
61
62 PGM_LOCK_ASSERT_OWNER(pVM); /* This cannot fail as we grab the lock in pgmR3SharedModuleRegRendezvous before calling into ring-0. */
63
64 /*
65 * Check every region of the shared module.
66 */
67 for (uint32_t idxRegion = 0; idxRegion < pModule->cRegions; idxRegion++)
68 {
69 RTGCPTR GCPtrPage = paRegionsGCPtrs[idxRegion] & ~(RTGCPTR)GUEST_PAGE_OFFSET_MASK;
70 uint32_t cbLeft = pModule->aRegions[idxRegion].cb; Assert(!(cbLeft & GUEST_PAGE_OFFSET_MASK));
71 uint32_t idxPage = 0;
72
73 while (cbLeft)
74 {
75 /** @todo inefficient to fetch each guest page like this... */
76 PGMPTWALK Walk;
77 rc = PGMGstGetPage(pVCpu, GCPtrPage, &Walk);
78 if ( rc == VINF_SUCCESS
79 && !(Walk.fEffective & X86_PTE_RW)) /* important as we make assumptions about this below! */
80 {
81 PPGMPAGE pPage = pgmPhysGetPage(pVM, Walk.GCPhys);
82 Assert(!pPage || !PGM_PAGE_IS_BALLOONED(pPage));
83 if ( pPage
84 && PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED
85 && PGM_PAGE_GET_READ_LOCKS(pPage) == 0
86 && PGM_PAGE_GET_WRITE_LOCKS(pPage) == 0 )
87 {
88 PageDesc.idPage = PGM_PAGE_GET_PAGEID(pPage);
89 PageDesc.HCPhys = PGM_PAGE_GET_HCPHYS(pPage);
90 PageDesc.GCPhys = Walk.GCPhys;
91
92 rc = GMMR0SharedModuleCheckPage(pGVM, pModule, idxRegion, idxPage, &PageDesc);
93 if (RT_FAILURE(rc))
94 break;
95
96 /*
97 * Any change for this page?
98 */
99 if (PageDesc.idPage != NIL_GMM_PAGEID)
100 {
101 Assert(PGM_PAGE_GET_STATE(pPage) == PGM_PAGE_STATE_ALLOCATED);
102
103 Log(("PGMR0SharedModuleCheck: shared page gst virt=%RGv phys=%RGp host %RHp->%RHp\n",
104 GCPtrPage, PageDesc.GCPhys, PGM_PAGE_GET_HCPHYS(pPage), PageDesc.HCPhys));
105
106 /* Page was either replaced by an existing shared
107 version of it or converted into a read-only shared
108 page, so, clear all references. */
109 bool fFlush = false;
110 rc = pgmPoolTrackUpdateGCPhys(pVM, PageDesc.GCPhys, pPage, true /* clear the entries */, &fFlush);
111 Assert( rc == VINF_SUCCESS
112 || ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3)
113 && (pVCpu->pgm.s.fSyncFlags & PGM_SYNC_CLEAR_PGM_POOL)));
114 if (rc == VINF_SUCCESS)
115 fFlushTLBs |= fFlush;
116 fFlushRemTLBs = true;
117
118 if (PageDesc.HCPhys != PGM_PAGE_GET_HCPHYS(pPage))
119 {
120 /* Update the physical address and page id now. */
121 PGM_PAGE_SET_HCPHYS(pVM, pPage, PageDesc.HCPhys);
122 PGM_PAGE_SET_PAGEID(pVM, pPage, PageDesc.idPage);
123
124 /* Invalidate page map TLB entry for this page too. */
125 pgmPhysInvalidatePageMapTLBEntry(pVM, PageDesc.GCPhys);
126 pVM->pgm.s.cReusedSharedPages++;
127 }
128 /* else: nothing changed (== this page is now a shared
129 page), so no need to flush anything. */
130
131 pVM->pgm.s.cSharedPages++;
132 pVM->pgm.s.cPrivatePages--;
133 PGM_PAGE_SET_STATE(pVM, pPage, PGM_PAGE_STATE_SHARED);
134
135# ifdef VBOX_STRICT /* check sum hack */
136 pPage->s.u2Unused0 = PageDesc.u32StrictChecksum & 3;
137 //pPage->s.u2Unused1 = (PageDesc.u32StrictChecksum >> 8) & 3;
138# endif
139 }
140 }
141 }
142 else
143 {
144 Assert( rc == VINF_SUCCESS
145 || rc == VERR_PAGE_NOT_PRESENT
146 || rc == VERR_PAGE_MAP_LEVEL4_NOT_PRESENT
147 || rc == VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT
148 || rc == VERR_PAGE_TABLE_NOT_PRESENT);
149 rc = VINF_SUCCESS; /* ignore error */
150 }
151
152 idxPage++;
153 GCPtrPage += HOST_PAGE_SIZE;
154 cbLeft -= HOST_PAGE_SIZE;
155 }
156 }
157
158 /*
159 * Do TLB flushing if necessary.
160 */
161 if (fFlushTLBs)
162 PGM_INVL_ALL_VCPU_TLBS(pVM);
163
164 if (fFlushRemTLBs)
165 for (VMCPUID idCurCpu = 0; idCurCpu < pGVM->cCpus; idCurCpu++)
166 CPUMSetChangedFlags(&pGVM->aCpus[idCurCpu], CPUM_CHANGED_GLOBAL_TLB_FLUSH);
167
168 return rc;
169}
170#endif /* VBOX_WITH_PAGE_SHARING */
171
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