VMM.cpp revision a40c05ca69e15a5efdd0796ef52e26ec0b1bc4d2
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * VMM - The Virtual Machine Monitor Core.
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * Copyright (C) 2006-2007 innotek GmbH
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * available from http://www.virtualbox.org. This file is free software;
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * you can redistribute it and/or modify it under the terms of the GNU
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * General Public License (GPL) as published by the Free Software
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync//#define NO_SUPCALLR0VMM
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** @page pg_vmm VMM - The Virtual Machine Monitor
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * !Revise this! It's already incorrect!
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * The Virtual Machine Monitor (VMM) is the core of the virtual machine. It
43747b1f0bc8302a238fb35e55857a5e9aa1933dvboxsync * manages the alternate reality; controlling the virtualization, managing
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * resources, tracking CPU state, it's resources and so on...
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * We will split the VMM into smaller entities:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Virtual Machine Core Monitor (VMCM), which purpose it is to
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * provide ring and world switching, that including routing
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * interrupts to the host OS and traps to the appropriate trap
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * handlers. It will implement an external interface for
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * managing trap handlers.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - CPU Monitor (CM), tracking the state of the CPU (in the alternate
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * reality) and implementing external interfaces to read and change
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * the state.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Memory Monitor (MM), which purpose it is to virtualize physical
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * pages, segment descriptor tables, interrupt descriptor tables, task
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * segments, and keep track of all memory providing external interfaces
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * to access content and map pages. (Internally splitt into smaller entities!)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - IO Monitor (IOM), which virtualizes in and out I/O operations. It
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * interacts with the MM to implement memory mapped I/O. External
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * interfaces for adding and removing I/O ranges are implemented.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - External Interrupt Monitor (EIM), which purpose it is to manage
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * interrupts generated by virtual devices. This monitor provides
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * an interfaces for raising interrupts which is accessible at any
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * time and from all thread.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * A subentity of the EIM is the vitual Programmable Interrupt
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Controller Device (VPICD), and perhaps a virtual I/O Advanced
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Programmable Interrupt Controller Device (VAPICD).
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Direct Memory Access Monitor (DMAM), which purpose it is to support
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * virtual device using the DMA controller. Interfaces must be as the
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * EIM interfaces independent and threadable.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * A subentity of the DMAM is a virtual DMA Controller Device (VDMACD).
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Entities working on a higher level:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Device Manager (DM), which is a support facility for virtualized
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * hardware. This provides generic facilities for efficient device
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * virtualization. It will manage device attaching and detaching
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * conversing with EIM and IOM.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Debugger Facility (DBGF) provides the basic features for
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * debugging the alternate reality execution.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @section pg_vmm_s_use_cases Use Cases
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @subsection pg_vmm_s_use_case_boot Bootstrap
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Basic Init:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Init SUPDRV.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Init Virtual Machine Instance:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Load settings.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Check resource requirements (memory, com, stuff).
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Init Host Ring 3 part:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Init Core code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Load Pluggable Components.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Init Pluggable Components.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Init Host Ring 0 part:
98427c0ab08697e468c26dc33ee9571308577867vboxsync * - Load Core (core = core components like VMM, RMI, CA, and so on) code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Init Core code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Load Pluggable Component code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Init Pluggable Component code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Allocate first chunk of memory and pin it down. This block of memory
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * will fit the following pieces:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Virtual Machine Instance data. (Config, CPU state, VMM state, ++)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * (This is available from everywhere (at different addresses though)).
98427c0ab08697e468c26dc33ee9571308577867vboxsync * - VMM Guest Context code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Pluggable devices Guest Context code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Page tables (directory and everything) for the VMM Guest
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Setup Guest (Ring 0) part:
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Setup initial page tables (i.e. directory all the stuff).
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Load Core Guest Context code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * - Load Pluggable Devices Guest Context code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*******************************************************************************
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync* Header Files *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync*******************************************************************************/
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** The saved state version. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*******************************************************************************
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync* Internal Functions *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync*******************************************************************************/
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic DECLCALLBACK(int) vmmR3Save(PVM pVM, PSSMHANDLE pSSM);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic DECLCALLBACK(int) vmmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic DECLCALLBACK(void) vmmR3YieldEMT(PVM pVM, PTMTIMER pTimer, void *pvUser);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic DECLCALLBACK(void) vmmR3InfoFF(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*******************************************************************************
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync* Global Variables *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync*******************************************************************************/
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** Array of switcher defininitions.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * The type and index shall match!
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic PVMMSWITCHERDEF s_apSwitchers[VMMSWITCHER_MAX] =
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Initiates the core code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * This is core per VM code which might need fixups and/or for ease of use
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * are put on linear contiguous backing.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @returns VBox status code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param pVM Pointer to VM structure.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Calc the size.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync unsigned cbCoreCode = 0;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync for (unsigned iSwitcher = 0; iSwitcher < ELEMENTS(s_apSwitchers); iSwitcher++)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync PVMMSWITCHERDEF pSwitcher = s_apSwitchers[iSwitcher];
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertRelease((unsigned)pSwitcher->enmType == iSwitcher);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync cbCoreCode += RT_ALIGN_32(pSwitcher->cbCode + 1, 32);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Allocate continguous pages for switchers and deal with
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * conflicts in the intermediate mapping of the code.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pVM->vmm.s.cbCoreCode = RT_ALIGN_32(cbCoreCode, PAGE_SIZE);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync pVM->vmm.s.pvHCCoreCodeR3 = SUPContAlloc2(pVM->vmm.s.cbCoreCode >> PAGE_SHIFT, &pVM->vmm.s.pvHCCoreCodeR0, &pVM->vmm.s.HCPhysCoreCode);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync rc = PGMR3MapIntermediate(pVM, pVM->vmm.s.pvHCCoreCodeR0, pVM->vmm.s.HCPhysCoreCode, cbCoreCode);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* try more allocations. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync unsigned i = 0;
pVM->vmm.s.pvHCCoreCodeR3 = SUPContAlloc2(pVM->vmm.s.cbCoreCode >> PAGE_SHIFT, &pVM->vmm.s.pvHCCoreCodeR0, &pVM->vmm.s.HCPhysCoreCode);
if (pSwitcher)
rc = MMR3HyperMapHCPhys(pVM, pVM->vmm.s.pvHCCoreCodeR3, pVM->vmm.s.HCPhysCoreCode, cbCoreCode, "Core Code", &pVM->vmm.s.pvGCCoreCode);
pVM->vmm.s.pvHCCoreCodeR3, pVM->vmm.s.pvHCCoreCodeR0, pVM->vmm.s.pvGCCoreCode, pVM->vmm.s.HCPhysCoreCode, pVM->vmm.s.cbCoreCode));
return rc;
AssertMsgFailed(("PGMR3Map(,%VGv, %VGp, %#x, 0) failed with rc=%Vrc\n", pVM->vmm.s.pvGCCoreCode, pVM->vmm.s.HCPhysCoreCode, cbCoreCode, rc));
return rc;
("pVM->vmm.padding is too small! vmm.padding %d while vmm.s is %d\n",
pVM->vmm.s.cYieldEveryMillies = 23; /* Value arrived at after experimenting with the grub boot prompt. */
//pVM->vmm.s.cYieldEveryMillies = 8; //debugging
AssertMsgRCReturn(rc, ("Configuration error. Failed to query \"YieldEMTInterval\", rc=%Vrc\n", rc), rc);
rc = SSMR3RegisterInternal(pVM, "vmm", 1, VMM_SAVED_STATE_VERSION, VMM_STACK_SIZE + sizeof(RTGCPTR),
return rc;
return rc;
#ifdef VBOX_STRICT_VMM_STACK
rc = MMHyperAlloc(pVM, VMM_STACK_SIZE + PAGE_SIZE + PAGE_SIZE, PAGE_SIZE, MM_TAG_VMM, (void **)&pVM->vmm.s.pbHCStack);
#ifdef LOG_ENABLED
if (pLogger)
* If you want to log in non-debug modes, you'll have to remember to change SUPDRvShared.c
* You might also wish to enable the AssertMsg1/2 overrides in VMMR0.cpp when enabling this.
//pVM->vmm.s.pR0Logger->fCreated = false;
if (pRelLogger)
#ifdef VBOX_WITH_NMI
STAM_REG(pVM, &pVM->vmm.s.StatRunGC, STAMTYPE_COUNTER, "/VMM/RunGC", STAMUNIT_OCCURENCES, "Number of context switches.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetNormal, STAMTYPE_COUNTER, "/VMM/GCRet/Normal", STAMUNIT_OCCURENCES, "Number of VINF_SUCCESS returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetInterrupt, STAMTYPE_COUNTER, "/VMM/GCRet/Interrupt", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_INTERRUPT returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetInterruptHyper, STAMTYPE_COUNTER, "/VMM/GCRet/InterruptHyper", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_INTERRUPT_HYPER returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetGuestTrap, STAMTYPE_COUNTER, "/VMM/GCRet/GuestTrap", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_GUEST_TRAP returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetRingSwitch, STAMTYPE_COUNTER, "/VMM/GCRet/RingSwitch", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_RING_SWITCH returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetRingSwitchInt, STAMTYPE_COUNTER, "/VMM/GCRet/RingSwitchInt", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_RING_SWITCH_INT returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetExceptionPrivilege, STAMTYPE_COUNTER, "/VMM/GCRet/ExceptionPrivilege", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_EXCEPTION_PRIVILEGED returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetStaleSelector, STAMTYPE_COUNTER, "/VMM/GCRet/StaleSelector", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_STALE_SELECTOR returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetIRETTrap, STAMTYPE_COUNTER, "/VMM/GCRet/IRETTrap", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_IRET_TRAP returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetEmulate, STAMTYPE_COUNTER, "/VMM/GCRet/Emulate", STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchEmulate, STAMTYPE_COUNTER, "/VMM/GCRet/PatchEmulate", STAMUNIT_OCCURENCES, "Number of VINF_PATCH_EMULATE_INSTR returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetIORead, STAMTYPE_COUNTER, "/VMM/GCRet/IORead", STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_IOPORT_READ returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetIOWrite, STAMTYPE_COUNTER, "/VMM/GCRet/IOWrite", STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_IOPORT_WRITE returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetMMIORead, STAMTYPE_COUNTER, "/VMM/GCRet/MMIORead", STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_MMIO_READ returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetMMIOWrite, STAMTYPE_COUNTER, "/VMM/GCRet/MMIOWrite", STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_MMIO_WRITE returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetMMIOReadWrite, STAMTYPE_COUNTER, "/VMM/GCRet/MMIOReadWrite", STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_MMIO_READ_WRITE returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetMMIOPatchRead, STAMTYPE_COUNTER, "/VMM/GCRet/MMIOPatchRead", STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_MMIO_PATCH_READ returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetMMIOPatchWrite, STAMTYPE_COUNTER, "/VMM/GCRet/MMIOPatchWrite", STAMUNIT_OCCURENCES, "Number of VINF_IOM_HC_MMIO_PATCH_WRITE returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetLDTFault, STAMTYPE_COUNTER, "/VMM/GCRet/LDTFault", STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION_GDT_FAULT returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetGDTFault, STAMTYPE_COUNTER, "/VMM/GCRet/GDTFault", STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION_LDT_FAULT returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetIDTFault, STAMTYPE_COUNTER, "/VMM/GCRet/IDTFault", STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION_IDT_FAULT returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetTSSFault, STAMTYPE_COUNTER, "/VMM/GCRet/TSSFault", STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION_TSS_FAULT returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetPDFault, STAMTYPE_COUNTER, "/VMM/GCRet/PDFault", STAMUNIT_OCCURENCES, "Number of VINF_EM_EXECUTE_INSTRUCTION_PD_FAULT returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetCSAMTask, STAMTYPE_COUNTER, "/VMM/GCRet/CSAMTask", STAMUNIT_OCCURENCES, "Number of VINF_CSAM_PENDING_ACTION returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetSyncCR3, STAMTYPE_COUNTER, "/VMM/GCRet/SyncCR", STAMUNIT_OCCURENCES, "Number of VINF_PGM_SYNC_CR3 returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetMisc, STAMTYPE_COUNTER, "/VMM/GCRet/Misc", STAMUNIT_OCCURENCES, "Number of misc returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchInt3, STAMTYPE_COUNTER, "/VMM/GCRet/PatchInt3", STAMUNIT_OCCURENCES, "Number of VINF_PATM_PATCH_INT3 returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchPF, STAMTYPE_COUNTER, "/VMM/GCRet/PatchPF", STAMUNIT_OCCURENCES, "Number of VINF_PATM_PATCH_TRAP_PF returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchGP, STAMTYPE_COUNTER, "/VMM/GCRet/PatchGP", STAMUNIT_OCCURENCES, "Number of VINF_PATM_PATCH_TRAP_GP returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchIretIRQ, STAMTYPE_COUNTER, "/VMM/GCRet/PatchIret", STAMUNIT_OCCURENCES, "Number of VINF_PATM_PENDING_IRQ_AFTER_IRET returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetPageOverflow, STAMTYPE_COUNTER, "/VMM/GCRet/InvlpgOverflow", STAMUNIT_OCCURENCES, "Number of VERR_REM_FLUSHED_PAGES_OVERFLOW returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetRescheduleREM, STAMTYPE_COUNTER, "/VMM/GCRet/ScheduleREM", STAMUNIT_OCCURENCES, "Number of VINF_EM_RESCHEDULE_REM returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetToR3, STAMTYPE_COUNTER, "/VMM/GCRet/ToR3", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_TO_R3 returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetTimerPending, STAMTYPE_COUNTER, "/VMM/GCRet/TimerPending", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_TIMER_PENDING returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetInterruptPending, STAMTYPE_COUNTER, "/VMM/GCRet/InterruptPending", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_INTERRUPT_PENDING returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetCallHost, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/Misc", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetPGMGrowRAM, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/GrowRAM", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetPDMLock, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/PDMLock", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetLogFlush, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/LogFlush", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetPDMQueueFlush, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/QueueFlush", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetPGMPoolGrow, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/PGMPoolGrow",STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetRemReplay, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/REMReplay", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetVMSetError, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/VMSetError", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetPGMLock, STAMTYPE_COUNTER, "/VMM/GCRet/CallHost/PGMLock", STAMUNIT_OCCURENCES, "Number of VINF_VMM_CALL_HOST returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetPATMDuplicateFn, STAMTYPE_COUNTER, "/VMM/GCRet/PATMDuplicateFn", STAMUNIT_OCCURENCES, "Number of VINF_PATM_DUPLICATE_FUNCTION returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetPGMChangeMode, STAMTYPE_COUNTER, "/VMM/GCRet/PGMChangeMode", STAMUNIT_OCCURENCES, "Number of VINF_PGM_CHANGE_MODE returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetEmulHlt, STAMTYPE_COUNTER, "/VMM/GCRet/EmulHlt", STAMUNIT_OCCURENCES, "Number of VINF_EM_RAW_EMULATE_INSTR_HLT returns.");
STAM_REG(pVM, &pVM->vmm.s.StatGCRetPendingRequest, STAMTYPE_COUNTER, "/VMM/GCRet/PendingRequest", STAMUNIT_OCCURENCES, "Number of VINF_EM_PENDING_REQUEST returns.");
return VINF_SUCCESS;
return rc;
#ifdef VBOX_STRICT_VMM_STACK
* Two inaccessible pages at each sides of the stack to catch over/under-flows.
int rc = PGMMapSetPage(pVM, pVM->vmm.s.pbGCStack, VMM_STACK_SIZE, X86_PTE_P | X86_PTE_A | X86_PTE_D | X86_PTE_RW);
rc = TMR3TimerCreateInternal(pVM, TMCLOCK_REAL, vmmR3YieldEMT, NULL, "EMT Yielder", &pVM->vmm.s.pYieldTimer);
#ifdef VBOX_WITH_NMI
return rc;
int rc;
return rc;
#ifdef NO_SUPCALLR0VMM
return rc;
return VINF_SUCCESS;
#ifdef NO_SUPCALLR0VMM
#ifdef LOG_ENABLED
if ( pLogger
return rc;
int rc;
#ifdef NO_SUPCALLR0VMM
#ifdef VBOX_STRICT_VMM_STACK
return rc;
int rc = PDMR3GetSymbolGC(pVM, VMMGC_MAIN_MODULE_NAME, "CPUMGCResumeGuest", &pVM->vmm.s.pfnCPUMGCResumeGuest);
rc = PDMR3GetSymbolGC(pVM, VMMGC_MAIN_MODULE_NAME, "CPUMGCResumeGuestV86", &pVM->vmm.s.pfnCPUMGCResumeGuestV86);
if (pR0Logger)
return rc;
static void vmmR3SwitcherGenericRelocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode,
const void *pv;
uintptr_t u;
uintptr_t u;
} uSrc;
switch (u8)
case FIX_HC_2_GC_NEAR_REL:
Assert(offSrc - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offSrc - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);
case FIX_HC_2_ID_NEAR_REL:
Assert(offSrc - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offSrc - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);
Assert(offTrg - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offTrg - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);
case FIX_GC_2_HC_NEAR_REL:
Assert(offTrg - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offTrg - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);
case FIX_GC_2_ID_NEAR_REL:
Assert(offTrg - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offTrg - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);
case FIX_ID_2_HC_NEAR_REL:
Assert(offSrc - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offSrc - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);
Assert(offTrg - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offTrg - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);
case FIX_ID_2_GC_NEAR_REL:
Assert(offSrc - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offSrc - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);
case FIX_GC_FAR32:
case FIX_GC_CPUM_OFF:
case FIX_GC_VM_OFF:
case FIX_HC_CPUM_OFF:
case FIX_HC_VM_OFF:
case FIX_INTER_32BIT_CR3:
case FIX_INTER_PAE_CR3:
case FIX_INTER_AMD64_CR3:
case FIX_HYPER_32BIT_CR3:
case FIX_HYPER_PAE_CR3:
case FIX_HYPER_AMD64_CR3:
case FIX_HYPER_CS:
case FIX_HYPER_DS:
case FIX_HYPER_TSS:
case FIX_GC_TSS_GDTE_DW2:
case FIX_NO_FXSAVE_JMP:
case FIX_NO_SYSENTER_JMP:
case FIX_NO_SYSCALL_JMP:
case FIX_HC_32BIT:
Assert(offTrg - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offTrg - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);
case FIX_HC_64BIT:
Assert(offTrg - pSwitcher->offHCCode0 < pSwitcher->cbHCCode0 || offTrg - pSwitcher->offHCCode1 < pSwitcher->cbHCCode1);
case FIX_HC_64BIT_CS:
case FIX_HC_64BIT_CPUM:
case FIX_ID_32BIT:
Assert(offTrg - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offTrg - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);
case FIX_ID_64BIT:
Assert(offTrg - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offTrg - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);
Assert(offTrg - pSwitcher->offIDCode0 < pSwitcher->cbIDCode0 || offTrg - pSwitcher->offIDCode1 < pSwitcher->cbIDCode1);
#ifdef VBOX_WITH_NMI
case FIX_GC_APIC_BASE_32BIT:
#ifdef LOG_ENABLED
if (LogIs2Enabled())
offCode++;
while (cbCode > 0)
if (RT_SUCCESS(DISInstr(&Cpu, (RTUINTPTR)pu8CodeR3 + offCode, uBase - (RTUINTPTR)pu8CodeR3, &cbInstr, szDisas)))
DECLCALLBACK(void) vmmR3Switcher32BitTo32Bit_Relocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode)
DECLCALLBACK(void) vmmR3Switcher32BitToPAE_Relocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode)
DECLCALLBACK(void) vmmR3SwitcherPAETo32Bit_Relocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode)
DECLCALLBACK(void) vmmR3SwitcherPAEToPAE_Relocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode)
DECLCALLBACK(void) vmmR3SwitcherAMD64ToPAE_Relocate(PVM pVM, PVMMSWITCHERDEF pSwitcher, uint8_t *pu8CodeR0, uint8_t *pu8CodeR3, RTGCPTR GCPtrCode, uint32_t u32IDCode)
SELMGetHyperCS(pVM), SELMGetHyperDS(pVM), SELMGetHyperTSS(pVM), SELMGetHyperGDT(pVM), SELMGetHyperCS64(pVM));
return NULL;
return NULL;
return rc;
|| (GCPtrStackBottom - GCPtrESP < 32)) /** @todo This will break if we start preemting the hypervisor. */
return rc;
if (u32 != ~0U)
return VINF_SUCCESS;
LogRel(("The stack is not in the same place and it's not empty! GCPtrStackBottom=%VGv pbGCStackBottom=%VGv ESP=%VGv\n",
AssertFailed();
return VERR_SSM_LOAD_CONFIG_MISMATCH;
return VERR_INVALID_PARAMETER;
if (pSwitcher)
Log(("VMMR3SelectSwitcher: enmSwitcher %d -> %d %s\n", pVM->vmm.s.enmSwitcher, enmSwitcher, pSwitcher->pszDesc));
RTR0PTR pbCodeR0 = (RTR0PTR)pVM->vmm.s.pvHCCoreCodeR0 + pVM->vmm.s.aoffSwitchers[enmSwitcher]; /** @todo fix the pvHCCoreCodeR0 type */
return VINF_SUCCESS;
return VERR_NOT_IMPLEMENTED;
* And then check for fSwitcherDisabled in VMMR3SelectSwitcher() in order to prevent it from being removed.
return VINF_SUCCESS;
return VERR_SYMBOL_NOT_FOUND;
return VINF_SUCCESS;
#ifdef LOG_ENABLED
int rc;
#ifdef NO_SUPCALLR0VMM
#ifdef LOG_ENABLED
if ( pLogger
Log2(("VMMR3RawRunGC: returns %Vrc (cs:eip=%04x:%08x)\n", rc, CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));
return rc;
return rc;
int rc;
#ifdef NO_SUPCALLR0VMM
#ifdef LOG_ENABLED
if ( pR0Logger
Log2(("VMMR3HwAccRunGC: returns %Vrc (cs:eip=%04x:%08x)\n", rc, CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));
return rc;
return rc;
return rc;
int i = cArgs;
int rc;
#ifdef NO_SUPCALLR0VMM
#ifdef LOG_ENABLED
if ( pLogger
Log2(("VMMR3CallGCV: returns %Vrc (cs:eip=%04x:%08x)\n", rc, CPUMGetGuestCS(pVM), CPUMGetGuestEIP(pVM)));
return rc;
return rc;
int rc;
#ifdef NO_SUPCALLR0VMM
#ifdef LOG_ENABLED
if ( pLogger
return rc;
return rc;
case VMMCALLHOST_PDM_LOCK:
#ifndef NEW_PHYS_CODE
case VMMCALLHOST_PGM_LOCK:
case VMMCALLHOST_VM_SET_ERROR:
#ifdef RT_ARCH_X86
return VINF_EM_DBG_HYPER_ASSERTION;
return VERR_INTERNAL_ERROR;
return VINF_SUCCESS;
typedef struct VMMR3FATALDUMPINFOHLP
bool fStdErr;
static DECLCALLBACK(void) vmmR3FatalDumpInfoHlp_pfnPrintf(PCDBGFINFOHLP pHlp, const char *pszFormat, ...)
static DECLCALLBACK(void) vmmR3FatalDumpInfoHlp_pfnPrintfV(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args)
#ifndef LOG_ENABLED
#ifndef DEBUG_sandervl
pHlp->fStdErr = (!pHlp->pRelLogger || !(pHlp->pRelLogger->fDestFlags & (RTLOGDEST_STDOUT | RTLOGDEST_STDERR)))
bool fDoneHyper = false;
switch (rcErr)
case VERR_TRPM_DONT_PANIC:
case VERR_TRPM_PANIC:
case VINF_EM_RAW_IRET_TRAP:
uEIP);
// uEIP - (RTGCUINTPTR)pVM->vmm.s.pvGCCoreCode);
rc2 = DBGFR3DisasInstrEx(pVM, 0, 0, DBGF_DISAS_FLAGS_CURRENT_HYPER, &szInstr[0], sizeof(szInstr), NULL);
fDoneHyper = true;
if (offDisp > 0)
else if (offDisp < 0)
const char *pszInfo;
const char *pszArgs;
} const aInfo[] =
if (f & (flag)) \
f &= ~(flag); \