VirtualBox

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

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

#1865: Final VMM cleanups.

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