VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMGC/VMMGC.cpp@ 17236

Last change on this file since 17236 was 17146, checked in by vboxsync, 16 years ago

VBOX_WITH_PGMPOOL_PAGING_ONLY: Disable logging during a critical section in MapCR3 (raw mode only).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.9 KB
Line 
1/* $Id: VMMGC.cpp 17146 2009-02-26 09:23:27Z vboxsync $ */
2/** @file
3 * VMM - Raw-mode Context.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_VMM
27#include <VBox/vmm.h>
28#include <VBox/trpm.h>
29#include "VMMInternal.h"
30#include <VBox/vm.h>
31#include <VBox/sup.h>
32#include <VBox/err.h>
33#include <VBox/log.h>
34#include <iprt/asm.h>
35#include <iprt/assert.h>
36#include <iprt/initterm.h>
37
38
39/*******************************************************************************
40* Global Variables *
41*******************************************************************************/
42/** Default logger instance. */
43extern "C" DECLIMPORT(RTLOGGERRC) g_Logger;
44extern "C" DECLIMPORT(RTLOGGERRC) g_RelLogger;
45
46
47/*******************************************************************************
48* Internal Functions *
49*******************************************************************************/
50static int vmmGCTest(PVM pVM, unsigned uOperation, unsigned uArg);
51static DECLCALLBACK(int) vmmGCTestTmpPFHandler(PVM pVM, PCPUMCTXCORE pRegFrame);
52static DECLCALLBACK(int) vmmGCTestTmpPFHandlerCorruptFS(PVM pVM, PCPUMCTXCORE pRegFrame);
53
54
55
56/**
57 * The GC entry point.
58 *
59 * @returns VBox status code.
60 * @param pVM The VM to operate on.
61 * @param uOperation Which operation to execute (VMMGCOPERATION).
62 * @param uArg Argument to that operation.
63 */
64VMMRCDECL(int) VMMGCEntry(PVM pVM, unsigned uOperation, unsigned uArg, ...)
65{
66 /* todo */
67 switch (uOperation)
68 {
69 /*
70 * Init RC modules.
71 */
72 case VMMGC_DO_VMMGC_INIT:
73 {
74 /*
75 * Validate the svn revision (uArg).
76 */
77 if (uArg != VMMGetSvnRev())
78 return VERR_VERSION_MISMATCH;
79
80 /*
81 * Initialize the runtime.
82 * (The program timestamp is found in the elipsis.)
83 */
84 va_list va;
85 va_start(va, uArg);
86 uint64_t u64TS = va_arg(va, uint64_t);
87 va_end(va);
88
89 int rc = RTRCInit(u64TS);
90 Log(("VMMGCEntry: VMMGC_DO_VMMGC_INIT - uArg=%u (svn revision) u64TS=%RX64; rc=%Rrc\n", uArg, u64TS, rc));
91 AssertRCReturn(rc, rc);
92
93 return VINF_SUCCESS;
94 }
95
96 /*
97 * Testcase which is used to test interrupt forwarding.
98 * It spins for a while with interrupts enabled.
99 */
100 case VMMGC_DO_TESTCASE_HYPER_INTERRUPT:
101 {
102 uint32_t volatile i = 0;
103 ASMIntEnable();
104 while (i < _2G32)
105 i++;
106 ASMIntDisable();
107 return 0;
108 }
109
110 /*
111 * Testcase which simply returns, this is used for
112 * profiling of the switcher.
113 */
114 case VMMGC_DO_TESTCASE_NOP:
115 return 0;
116
117 /*
118 * Testcase executes a privileged instruction to force a world switch. (in both SVM & VMX)
119 */
120 case VMMGC_DO_TESTCASE_HWACCM_NOP:
121 ASMRdMsr_Low(MSR_IA32_SYSENTER_CS);
122 return 0;
123
124 /*
125 * Delay for ~100us.
126 */
127 case VMMGC_DO_TESTCASE_INTERRUPT_MASKING:
128 {
129 uint64_t u64MaxTicks = (SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage) != ~(uint64_t)0
130 ? SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage)
131 : _2G)
132 / 10000;
133 uint64_t u64StartTSC = ASMReadTSC();
134 uint64_t u64TicksNow;
135 uint32_t volatile i = 0;
136
137 do
138 {
139 /* waste some time and protect against getting stuck. */
140 for (uint32_t volatile j = 0; j < 1000; j++, i++)
141 if (i > _2G32)
142 return VERR_GENERAL_FAILURE;
143
144 /* check if we're done.*/
145 u64TicksNow = ASMReadTSC() - u64StartTSC;
146 } while (u64TicksNow < u64MaxTicks);
147
148 return VINF_SUCCESS;
149 }
150
151 /*
152 * Trap testcases and unknown operations.
153 */
154 default:
155 if ( uOperation >= VMMGC_DO_TESTCASE_TRAP_FIRST
156 && uOperation < VMMGC_DO_TESTCASE_TRAP_LAST)
157 return vmmGCTest(pVM, uOperation, uArg);
158 return VERR_INVALID_PARAMETER;
159 }
160}
161
162
163/**
164 * Internal RC logger worker: Flush logger.
165 *
166 * @returns VINF_SUCCESS.
167 * @param pLogger The logger instance to flush.
168 * @remark This function must be exported!
169 */
170VMMRCDECL(int) vmmGCLoggerFlush(PRTLOGGERRC pLogger)
171{
172 PVM pVM = &g_VM;
173 NOREF(pLogger);
174 return VMMGCCallHost(pVM, VMMCALLHOST_VMM_LOGGER_FLUSH, 0);
175}
176
177
178/**
179 * Disables the GC logger temporarily
180 *
181 * @param pVM The VM handle.
182 */
183VMMRCDECL(void) VMMGCLogDisable(PVM pVM)
184{
185 if (pVM->vmm.s.pRCLoggerRC)
186 pVM->vmm.s.pRCLoggerRC->fFlags |= RTLOGFLAGS_DISABLED;
187}
188
189
190/**
191 * Enables the GC logger again
192 *
193 * @param pVM The VM handle.
194 */
195VMMRCDECL(void) VMMGCLogEnable(PVM pVM)
196{
197 if (pVM->vmm.s.pRCLoggerRC)
198 pVM->vmm.s.pRCLoggerRC->fFlags &= ~RTLOGFLAGS_DISABLED;
199}
200
201
202/**
203 * Switches from guest context to host context.
204 *
205 * @param pVM The VM handle.
206 * @param rc The status code.
207 */
208VMMRCDECL(void) VMMGCGuestToHost(PVM pVM, int rc)
209{
210 pVM->vmm.s.pfnGuestToHostRC(rc);
211}
212
213
214/**
215 * Calls the ring-3 host code.
216 *
217 * @returns VBox status code of the ring-3 call.
218 * @param pVM The VM handle.
219 * @param enmOperation The operation.
220 * @param uArg The argument to the operation.
221 */
222VMMRCDECL(int) VMMGCCallHost(PVM pVM, VMMCALLHOST enmOperation, uint64_t uArg)
223{
224/** @todo profile this! */
225 pVM->vmm.s.enmCallHostOperation = enmOperation;
226 pVM->vmm.s.u64CallHostArg = uArg;
227 pVM->vmm.s.rcCallHost = VERR_INTERNAL_ERROR;
228 pVM->vmm.s.pfnGuestToHostRC(VINF_VMM_CALL_HOST);
229 return pVM->vmm.s.rcCallHost;
230}
231
232
233/**
234 * Execute the trap testcase.
235 *
236 * There is some common code here, that's why we're collecting them
237 * like this. Odd numbered variation (uArg) are executed with write
238 * protection (WP) enabled.
239 *
240 * @returns VINF_SUCCESS if it was a testcase setup up to continue and did so successfully.
241 * @returns VERR_NOT_IMPLEMENTED if the testcase wasn't implemented.
242 * @returns VERR_GENERAL_FAILURE if the testcase continued when it shouldn't.
243 *
244 * @param pVM The VM handle.
245 * @param uOperation The testcase.
246 * @param uArg The variation. See function description for odd / even details.
247 *
248 * @remark Careful with the trap 08 testcase and WP, it will tripple
249 * fault the box if the TSS, the Trap8 TSS and the fault TSS
250 * GDTE are in pages which are read-only.
251 * See bottom of SELMR3Init().
252 */
253static int vmmGCTest(PVM pVM, unsigned uOperation, unsigned uArg)
254{
255 /*
256 * Set up the testcase.
257 */
258#if 0
259 switch (uOperation)
260 {
261 default:
262 break;
263 }
264#endif
265
266 /*
267 * Enable WP if odd variation.
268 */
269 if (uArg & 1)
270 vmmGCEnableWP();
271
272 /*
273 * Execute the testcase.
274 */
275 int rc = VERR_NOT_IMPLEMENTED;
276 switch (uOperation)
277 {
278 //case VMMGC_DO_TESTCASE_TRAP_0:
279 //case VMMGC_DO_TESTCASE_TRAP_1:
280 //case VMMGC_DO_TESTCASE_TRAP_2:
281
282 case VMMGC_DO_TESTCASE_TRAP_3:
283 {
284 if (uArg <= 1)
285 rc = vmmGCTestTrap3();
286 break;
287 }
288
289 //case VMMGC_DO_TESTCASE_TRAP_4:
290 //case VMMGC_DO_TESTCASE_TRAP_5:
291 //case VMMGC_DO_TESTCASE_TRAP_6:
292 //case VMMGC_DO_TESTCASE_TRAP_7:
293
294 case VMMGC_DO_TESTCASE_TRAP_8:
295 {
296#ifndef DEBUG_bird /** @todo dynamic check that this won't tripple fault... */
297 if (uArg & 1)
298 break;
299#endif
300 if (uArg <= 1)
301 rc = vmmGCTestTrap8();
302 break;
303 }
304
305 //VMMGC_DO_TESTCASE_TRAP_9,
306 //VMMGC_DO_TESTCASE_TRAP_0A,
307 //VMMGC_DO_TESTCASE_TRAP_0B,
308 //VMMGC_DO_TESTCASE_TRAP_0C,
309
310 case VMMGC_DO_TESTCASE_TRAP_0D:
311 {
312 if (uArg <= 1)
313 rc = vmmGCTestTrap0d();
314 break;
315 }
316
317 case VMMGC_DO_TESTCASE_TRAP_0E:
318 {
319 if (uArg <= 1)
320 rc = vmmGCTestTrap0e();
321 else if (uArg == 2 || uArg == 4)
322 {
323 /*
324 * Test the use of a temporary #PF handler.
325 */
326 rc = TRPMGCSetTempHandler(pVM, X86_XCPT_PF, uArg != 4 ? vmmGCTestTmpPFHandler : vmmGCTestTmpPFHandlerCorruptFS);
327 if (RT_SUCCESS(rc))
328 {
329 rc = vmmGCTestTrap0e();
330
331 /* in case it didn't fire. */
332 int rc2 = TRPMGCSetTempHandler(pVM, X86_XCPT_PF, NULL);
333 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
334 rc = rc2;
335 }
336 }
337 break;
338 }
339 }
340
341 /*
342 * Re-enable WP.
343 */
344 if (uArg & 1)
345 vmmGCDisableWP();
346
347 return rc;
348}
349
350
351/**
352 * Temporary #PF trap handler for the #PF test case.
353 *
354 * @returns VBox status code (appropriate for GC return).
355 * In this context RT_SUCCESS means to restart the instruction.
356 * @param pVM VM handle.
357 * @param pRegFrame Trap register frame.
358 */
359static DECLCALLBACK(int) vmmGCTestTmpPFHandler(PVM pVM, PCPUMCTXCORE pRegFrame)
360{
361 if (pRegFrame->eip == (uintptr_t)vmmGCTestTrap0e_FaultEIP)
362 {
363 pRegFrame->eip = (uintptr_t)vmmGCTestTrap0e_ResumeEIP;
364 return VINF_SUCCESS;
365 }
366 return VERR_INTERNAL_ERROR;
367}
368
369
370/**
371 * Temporary #PF trap handler for the #PF test case, this one messes up the fs selector.
372 *
373 * @returns VBox status code (appropriate for GC return).
374 * In this context RT_SUCCESS means to restart the instruction.
375 * @param pVM VM handle.
376 * @param pRegFrame Trap register frame.
377 */
378static DECLCALLBACK(int) vmmGCTestTmpPFHandlerCorruptFS(PVM pVM, PCPUMCTXCORE pRegFrame)
379{
380 int rc = vmmGCTestTmpPFHandler(pVM, pRegFrame);
381 pRegFrame->fs = 0x30;
382 return rc;
383}
384
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