VirtualBox

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

Last change on this file since 49282 was 49147, checked in by vboxsync, 11 years ago

tstVMM/msr: Formatting bug on 32-bit hosts, a cast got lost in a revision of the code. :/ Run the test with interrupts enabled and query 4/16 times more MSRs in one go.

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