VirtualBox

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

Last change on this file since 20873 was 20873, checked in by vboxsync, 15 years ago

VMMGCCallHost -> VMMRZCallRing3[NoCpu].

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 10.5 KB
Line 
1/* $Id: VMMGC.cpp 20873 2009-06-24 02:08:38Z 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 if (pVM->vmm.s.fRCLoggerFlushingDisabled)
179 return VINF_SUCCESS; /* fail quietly. */
180 return VMMRZCallRing3NoCpu(pVM, VMMCALLHOST_VMM_LOGGER_FLUSH, 0);
181}
182
183
184/**
185 * Flush logger if almost full.
186 *
187 * @param pVM The VM handle.
188 */
189VMMRCDECL(void) VMMGCLogFlushIfFull(PVM pVM)
190{
191 if ( pVM->vmm.s.pRCLoggerRC
192 && pVM->vmm.s.pRCLoggerRC->offScratch >= (sizeof(pVM->vmm.s.pRCLoggerRC->achScratch)*3/4))
193 {
194 if (pVM->vmm.s.fRCLoggerFlushingDisabled)
195 return; /* fail quietly. */
196 VMMRZCallRing3NoCpu(pVM, VMMCALLHOST_VMM_LOGGER_FLUSH, 0);
197 }
198}
199
200
201/**
202 * Switches from guest context to host context.
203 *
204 * @param pVM The VM handle.
205 * @param rc The status code.
206 */
207VMMRCDECL(void) VMMGCGuestToHost(PVM pVM, int rc)
208{
209 pVM->vmm.s.pfnGuestToHostRC(rc);
210}
211
212
213/**
214 * Execute the trap testcase.
215 *
216 * There is some common code here, that's why we're collecting them
217 * like this. Odd numbered variation (uArg) are executed with write
218 * protection (WP) enabled.
219 *
220 * @returns VINF_SUCCESS if it was a testcase setup up to continue and did so successfully.
221 * @returns VERR_NOT_IMPLEMENTED if the testcase wasn't implemented.
222 * @returns VERR_GENERAL_FAILURE if the testcase continued when it shouldn't.
223 *
224 * @param pVM The VM handle.
225 * @param uOperation The testcase.
226 * @param uArg The variation. See function description for odd / even details.
227 *
228 * @remark Careful with the trap 08 testcase and WP, it will tripple
229 * fault the box if the TSS, the Trap8 TSS and the fault TSS
230 * GDTE are in pages which are read-only.
231 * See bottom of SELMR3Init().
232 */
233static int vmmGCTest(PVM pVM, unsigned uOperation, unsigned uArg)
234{
235 /*
236 * Set up the testcase.
237 */
238#if 0
239 switch (uOperation)
240 {
241 default:
242 break;
243 }
244#endif
245
246 /*
247 * Enable WP if odd variation.
248 */
249 if (uArg & 1)
250 vmmGCEnableWP();
251
252 /*
253 * Execute the testcase.
254 */
255 int rc = VERR_NOT_IMPLEMENTED;
256 switch (uOperation)
257 {
258 //case VMMGC_DO_TESTCASE_TRAP_0:
259 //case VMMGC_DO_TESTCASE_TRAP_1:
260 //case VMMGC_DO_TESTCASE_TRAP_2:
261
262 case VMMGC_DO_TESTCASE_TRAP_3:
263 {
264 if (uArg <= 1)
265 rc = vmmGCTestTrap3();
266 break;
267 }
268
269 //case VMMGC_DO_TESTCASE_TRAP_4:
270 //case VMMGC_DO_TESTCASE_TRAP_5:
271 //case VMMGC_DO_TESTCASE_TRAP_6:
272 //case VMMGC_DO_TESTCASE_TRAP_7:
273
274 case VMMGC_DO_TESTCASE_TRAP_8:
275 {
276#ifndef DEBUG_bird /** @todo dynamic check that this won't tripple fault... */
277 if (uArg & 1)
278 break;
279#endif
280 if (uArg <= 1)
281 rc = vmmGCTestTrap8();
282 break;
283 }
284
285 //VMMGC_DO_TESTCASE_TRAP_9,
286 //VMMGC_DO_TESTCASE_TRAP_0A,
287 //VMMGC_DO_TESTCASE_TRAP_0B,
288 //VMMGC_DO_TESTCASE_TRAP_0C,
289
290 case VMMGC_DO_TESTCASE_TRAP_0D:
291 {
292 if (uArg <= 1)
293 rc = vmmGCTestTrap0d();
294 break;
295 }
296
297 case VMMGC_DO_TESTCASE_TRAP_0E:
298 {
299 if (uArg <= 1)
300 rc = vmmGCTestTrap0e();
301 else if (uArg == 2 || uArg == 4)
302 {
303 /*
304 * Test the use of a temporary #PF handler.
305 */
306 rc = TRPMGCSetTempHandler(pVM, X86_XCPT_PF, uArg != 4 ? vmmGCTestTmpPFHandler : vmmGCTestTmpPFHandlerCorruptFS);
307 if (RT_SUCCESS(rc))
308 {
309 rc = vmmGCTestTrap0e();
310
311 /* in case it didn't fire. */
312 int rc2 = TRPMGCSetTempHandler(pVM, X86_XCPT_PF, NULL);
313 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
314 rc = rc2;
315 }
316 }
317 break;
318 }
319 }
320
321 /*
322 * Re-enable WP.
323 */
324 if (uArg & 1)
325 vmmGCDisableWP();
326
327 return rc;
328}
329
330
331/**
332 * Temporary #PF trap handler for the #PF test case.
333 *
334 * @returns VBox status code (appropriate for GC return).
335 * In this context RT_SUCCESS means to restart the instruction.
336 * @param pVM VM handle.
337 * @param pRegFrame Trap register frame.
338 */
339static DECLCALLBACK(int) vmmGCTestTmpPFHandler(PVM pVM, PCPUMCTXCORE pRegFrame)
340{
341 if (pRegFrame->eip == (uintptr_t)vmmGCTestTrap0e_FaultEIP)
342 {
343 pRegFrame->eip = (uintptr_t)vmmGCTestTrap0e_ResumeEIP;
344 return VINF_SUCCESS;
345 }
346 return VERR_INTERNAL_ERROR;
347}
348
349
350/**
351 * Temporary #PF trap handler for the #PF test case, this one messes up the fs selector.
352 *
353 * @returns VBox status code (appropriate for GC return).
354 * In this context RT_SUCCESS means to restart the instruction.
355 * @param pVM VM handle.
356 * @param pRegFrame Trap register frame.
357 */
358static DECLCALLBACK(int) vmmGCTestTmpPFHandlerCorruptFS(PVM pVM, PCPUMCTXCORE pRegFrame)
359{
360 int rc = vmmGCTestTmpPFHandler(pVM, pRegFrame);
361 pRegFrame->fs = 0x30;
362 return rc;
363}
364
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