VirtualBox

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

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

VMM: Switcher and TRPM fixes wrt hypervisor traps and tstVMM.

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