VirtualBox

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

Last change on this file since 18746 was 17422, checked in by vboxsync, 16 years ago

VMM: Do not forcibly enable RC logging in VMMGCLogEnabled! Renamed it to VMMGCLogRestore and made VMMGCLogDisable return a state indicator that should be passed to it.

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