VirtualBox

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

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

Further splitup of VMM (ring 0 jump buffer).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 11.6 KB
Line 
1/* $Id: VMMGC.cpp 19434 2009-05-06 13:58:35Z 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 PVMCPU pVCpu = VMMGetCpu0(pVM);
247
248/** @todo profile this! */
249 pVCpu->vmm.s.enmCallHostOperation = enmOperation;
250 pVCpu->vmm.s.u64CallHostArg = uArg;
251 pVCpu->vmm.s.rcCallHost = VERR_INTERNAL_ERROR;
252 pVM->vmm.s.pfnGuestToHostRC(VINF_VMM_CALL_HOST);
253 return pVCpu->vmm.s.rcCallHost;
254}
255
256
257/**
258 * Execute the trap testcase.
259 *
260 * There is some common code here, that's why we're collecting them
261 * like this. Odd numbered variation (uArg) are executed with write
262 * protection (WP) enabled.
263 *
264 * @returns VINF_SUCCESS if it was a testcase setup up to continue and did so successfully.
265 * @returns VERR_NOT_IMPLEMENTED if the testcase wasn't implemented.
266 * @returns VERR_GENERAL_FAILURE if the testcase continued when it shouldn't.
267 *
268 * @param pVM The VM handle.
269 * @param uOperation The testcase.
270 * @param uArg The variation. See function description for odd / even details.
271 *
272 * @remark Careful with the trap 08 testcase and WP, it will tripple
273 * fault the box if the TSS, the Trap8 TSS and the fault TSS
274 * GDTE are in pages which are read-only.
275 * See bottom of SELMR3Init().
276 */
277static int vmmGCTest(PVM pVM, unsigned uOperation, unsigned uArg)
278{
279 /*
280 * Set up the testcase.
281 */
282#if 0
283 switch (uOperation)
284 {
285 default:
286 break;
287 }
288#endif
289
290 /*
291 * Enable WP if odd variation.
292 */
293 if (uArg & 1)
294 vmmGCEnableWP();
295
296 /*
297 * Execute the testcase.
298 */
299 int rc = VERR_NOT_IMPLEMENTED;
300 switch (uOperation)
301 {
302 //case VMMGC_DO_TESTCASE_TRAP_0:
303 //case VMMGC_DO_TESTCASE_TRAP_1:
304 //case VMMGC_DO_TESTCASE_TRAP_2:
305
306 case VMMGC_DO_TESTCASE_TRAP_3:
307 {
308 if (uArg <= 1)
309 rc = vmmGCTestTrap3();
310 break;
311 }
312
313 //case VMMGC_DO_TESTCASE_TRAP_4:
314 //case VMMGC_DO_TESTCASE_TRAP_5:
315 //case VMMGC_DO_TESTCASE_TRAP_6:
316 //case VMMGC_DO_TESTCASE_TRAP_7:
317
318 case VMMGC_DO_TESTCASE_TRAP_8:
319 {
320#ifndef DEBUG_bird /** @todo dynamic check that this won't tripple fault... */
321 if (uArg & 1)
322 break;
323#endif
324 if (uArg <= 1)
325 rc = vmmGCTestTrap8();
326 break;
327 }
328
329 //VMMGC_DO_TESTCASE_TRAP_9,
330 //VMMGC_DO_TESTCASE_TRAP_0A,
331 //VMMGC_DO_TESTCASE_TRAP_0B,
332 //VMMGC_DO_TESTCASE_TRAP_0C,
333
334 case VMMGC_DO_TESTCASE_TRAP_0D:
335 {
336 if (uArg <= 1)
337 rc = vmmGCTestTrap0d();
338 break;
339 }
340
341 case VMMGC_DO_TESTCASE_TRAP_0E:
342 {
343 if (uArg <= 1)
344 rc = vmmGCTestTrap0e();
345 else if (uArg == 2 || uArg == 4)
346 {
347 /*
348 * Test the use of a temporary #PF handler.
349 */
350 rc = TRPMGCSetTempHandler(pVM, X86_XCPT_PF, uArg != 4 ? vmmGCTestTmpPFHandler : vmmGCTestTmpPFHandlerCorruptFS);
351 if (RT_SUCCESS(rc))
352 {
353 rc = vmmGCTestTrap0e();
354
355 /* in case it didn't fire. */
356 int rc2 = TRPMGCSetTempHandler(pVM, X86_XCPT_PF, NULL);
357 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
358 rc = rc2;
359 }
360 }
361 break;
362 }
363 }
364
365 /*
366 * Re-enable WP.
367 */
368 if (uArg & 1)
369 vmmGCDisableWP();
370
371 return rc;
372}
373
374
375/**
376 * Temporary #PF trap handler for the #PF test case.
377 *
378 * @returns VBox status code (appropriate for GC return).
379 * In this context RT_SUCCESS means to restart the instruction.
380 * @param pVM VM handle.
381 * @param pRegFrame Trap register frame.
382 */
383static DECLCALLBACK(int) vmmGCTestTmpPFHandler(PVM pVM, PCPUMCTXCORE pRegFrame)
384{
385 if (pRegFrame->eip == (uintptr_t)vmmGCTestTrap0e_FaultEIP)
386 {
387 pRegFrame->eip = (uintptr_t)vmmGCTestTrap0e_ResumeEIP;
388 return VINF_SUCCESS;
389 }
390 return VERR_INTERNAL_ERROR;
391}
392
393
394/**
395 * Temporary #PF trap handler for the #PF test case, this one messes up the fs selector.
396 *
397 * @returns VBox status code (appropriate for GC return).
398 * In this context RT_SUCCESS means to restart the instruction.
399 * @param pVM VM handle.
400 * @param pRegFrame Trap register frame.
401 */
402static DECLCALLBACK(int) vmmGCTestTmpPFHandlerCorruptFS(PVM pVM, PCPUMCTXCORE pRegFrame)
403{
404 int rc = vmmGCTestTmpPFHandler(pVM, pRegFrame);
405 pRegFrame->fs = 0x30;
406 return rc;
407}
408
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