VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR3/GCM.cpp

Last change on this file was 99739, checked in by vboxsync, 12 months ago

*: doxygen corrections (mostly about removing @returns from functions returning void).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.7 KB
Line 
1/** @file
2 * GCM - Guest Compatibility Manager.
3 */
4
5/*
6 * Copyright (C) 2022-2023 Oracle and/or its affiliates.
7 *
8 * This file is part of VirtualBox base platform packages, as
9 * available from https://www.virtualbox.org.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation, in version 3 of the
14 * License.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, see <https://www.gnu.org/licenses>.
23 *
24 * SPDX-License-Identifier: GPL-3.0-only
25 */
26
27/** @page pg_gcm GCM - The Guest Compatibility Manager
28 *
29 * The Guest Compatibility Manager provides run-time compatibility fixes
30 * for certain known guest bugs.
31 *
32 * @see grp_gcm
33 *
34 *
35 * @section sec_gcm_fixer Fixers
36 *
37 * A GCM fixer implements a collection of run-time helpers/patches suitable for
38 * a specific guest type. Several fixers can be active at the same time; for
39 * example OS/2 or Windows 9x need their own fixers, but can also runs DOS
40 * applications which need DOS-specific fixers.
41 *
42 * The concept of fixers exists to reduce the number of false positives to a
43 * minimum. Heuristics are used to decide whether a particular fix should be
44 * applied or not; restricting the number of applicable fixes minimizes the
45 * chance that a fix could be misapplied.
46 *
47 * The fixers are invisible to a guest. A common problem is division by zero
48 * caused by a software timing loop which cannot deal with fast CPUs (where
49 * "fast" very much depends on the era when the software was written). A fixer
50 * intercepts division by zero, recognizes known register contents and code
51 * sequence, modifies one or more registers to avoid a divide error, and
52 * restarts the instruction.
53 *
54 * It is not expected that the set of active fixers would be changed during
55 * the lifetime of the VM.
56 */
57
58
59/*********************************************************************************************************************************
60* Header Files *
61*********************************************************************************************************************************/
62#define LOG_GROUP LOG_GROUP_GIM
63#include <VBox/vmm/gcm.h>
64#include <VBox/vmm/hm.h>
65#include <VBox/vmm/ssm.h>
66#include <VBox/vmm/pdmdev.h>
67#include "GCMInternal.h"
68#include <VBox/vmm/vm.h>
69
70#include <VBox/log.h>
71
72#include <iprt/err.h>
73#include <iprt/semaphore.h>
74#include <iprt/string.h>
75
76
77/*********************************************************************************************************************************
78* Internal Functions *
79*********************************************************************************************************************************/
80static FNSSMINTSAVEEXEC gcmR3Save;
81static FNSSMINTLOADEXEC gcmR3Load;
82
83
84/**
85 * Initializes the GCM.
86 *
87 * @returns VBox status code.
88 * @param pVM The cross context VM structure.
89 */
90VMMR3_INT_DECL(int) GCMR3Init(PVM pVM)
91{
92 LogFlow(("GCMR3Init\n"));
93
94 /*
95 * Assert alignment and sizes.
96 */
97 AssertCompile(sizeof(pVM->gcm.s) <= sizeof(pVM->gcm.padding));
98
99 /*
100 * Register the saved state data unit.
101 */
102 int rc = SSMR3RegisterInternal(pVM, "GCM", 0 /* uInstance */, GCM_SAVED_STATE_VERSION, sizeof(GCM),
103 NULL /* pfnLivePrep */, NULL /* pfnLiveExec */, NULL /* pfnLiveVote*/,
104 NULL /* pfnSavePrep */, gcmR3Save, NULL /* pfnSaveDone */,
105 NULL /* pfnLoadPrep */, gcmR3Load, NULL /* pfnLoadDone */);
106 if (RT_FAILURE(rc))
107 return rc;
108
109 /*
110 * Read configuration.
111 */
112 PCFGMNODE pCfgNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "GCM/");
113
114 /*
115 * Validate the GCM settings.
116 */
117 rc = CFGMR3ValidateConfig(pCfgNode, "/GCM/", /* pszNode */
118 "FixerSet", /* pszValidValues */
119 "", /* pszValidNodes */
120 "GCM", /* pszWho */
121 0); /* uInstance */
122 if (RT_FAILURE(rc))
123 return rc;
124
125#if 1
126 /** @cfgm{/GCM/FixerSet, uint32_t, 0}
127 * The set (bit mask) of enabled fixers. See GCMFIXERID.
128 */
129 uint32_t u32FixerIds;
130 rc = CFGMR3QueryU32Def(pCfgNode, "FixerSet", &u32FixerIds, 0);
131 AssertRCReturn(rc, rc);
132
133 /* Check for unknown bits. */
134 uint32_t u32BadBits = u32FixerIds & ~(GCMFIXER_DBZ_DOS | GCMFIXER_DBZ_OS2 | GCMFIXER_DBZ_WIN9X);
135
136 if (u32BadBits)
137 {
138 rc = VMR3SetError(pVM->pUVM, VERR_CFGM_CONFIG_UNKNOWN_VALUE, RT_SRC_POS, "Unsupported GCM fixer bits (%#x) set.", u32BadBits);
139 }
140 else
141 {
142 pVM->gcm.s.enmFixerIds = u32FixerIds;
143 }
144#else
145 pVM->gcm.s.enmFixerIds = GCMFIXER_DBZ_OS2 | GCMFIXER_DBZ_DOS | GCMFIXER_DBZ_WIN9X;
146#endif
147 LogRel(("GCM: Initialized (fixer bits: %#x)\n", u32FixerIds));
148
149 return rc;
150}
151
152
153/**
154 * Finalize the GCM initialization.
155 *
156 * This is called after initializing HM and most other VMM components.
157 *
158 * @returns VBox status code.
159 * @param pVM The cross context VM structure.
160 * @thread EMT(0)
161 */
162VMMR3_INT_DECL(int) GCMR3InitCompleted(PVM pVM)
163{
164 RT_NOREF(pVM);
165 return VINF_SUCCESS;
166}
167
168
169/**
170 * @callback_method_impl{FNSSMINTSAVEEXEC}
171 */
172static DECLCALLBACK(int) gcmR3Save(PVM pVM, PSSMHANDLE pSSM)
173{
174 AssertReturn(pVM, VERR_INVALID_PARAMETER);
175 AssertReturn(pSSM, VERR_SSM_INVALID_STATE);
176
177 int rc = VINF_SUCCESS;
178
179 /*
180 * Save per-VM data.
181 */
182 SSMR3PutU32(pSSM, pVM->gcm.s.enmFixerIds);
183
184 return rc;
185}
186
187
188/**
189 * @callback_method_impl{FNSSMINTLOADEXEC}
190 */
191static DECLCALLBACK(int) gcmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
192{
193 if (uPass != SSM_PASS_FINAL)
194 return VINF_SUCCESS;
195 if (uVersion != GCM_SAVED_STATE_VERSION)
196 return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
197
198 int rc;
199
200 /*
201 * Load per-VM data.
202 */
203 uint32_t uFixerIds;
204
205 rc = SSMR3GetU32(pSSM, &uFixerIds);
206 AssertRCReturn(rc, rc);
207
208 if ((GCMFIXERID)uFixerIds != pVM->gcm.s.enmFixerIds)
209 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Saved GCM fixer set %#X differs from the configured one (%#X)."),
210 uFixerIds, pVM->gcm.s.enmFixerIds);
211
212 return VINF_SUCCESS;
213}
214
215
216/**
217 * Terminates the GCM.
218 *
219 * Termination means cleaning up and freeing all resources,
220 * the VM itself is, at this point, powered off or suspended.
221 *
222 * @returns VBox status code.
223 * @param pVM The cross context VM structure.
224 */
225VMMR3_INT_DECL(int) GCMR3Term(PVM pVM)
226{
227 RT_NOREF(pVM);
228 return VINF_SUCCESS;
229}
230
231
232/**
233 * Applies relocations to data and code managed by this
234 * component. This function will be called at init and
235 * whenever the VMM need to relocate itself inside the GC.
236 *
237 * @param pVM The cross context VM structure.
238 * @param offDelta Relocation delta relative to old location.
239 */
240VMMR3_INT_DECL(void) GCMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
241{
242 RT_NOREF(pVM);
243 RT_NOREF(offDelta);
244}
245
246
247/**
248 * The VM is being reset.
249 *
250 * Do whatever fixer-specific resetting that needs to be done.
251 *
252 * @param pVM The cross context VM structure.
253 */
254VMMR3_INT_DECL(void) GCMR3Reset(PVM pVM)
255{
256 RT_NOREF(pVM);
257}
258
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use