VirtualBox

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

Last change on this file since 7821 was 5999, checked in by vboxsync, 17 years ago

The Giant CDDL Dual-License Header Change.

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