VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMRC/VMMRC.cpp@ 47627

Last change on this file since 47627 was 46861, checked in by vboxsync, 12 years ago

Don't allow mixing builds.

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