236b2935f217749893b7034e59da3e3568928acevboxsync * GIM - Guest Interface Manager.
aa7f783d8893b6004cb8d993273c008944f81544vboxsync * Copyright (C) 2014-2015 Oracle Corporation
236b2935f217749893b7034e59da3e3568928acevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
236b2935f217749893b7034e59da3e3568928acevboxsync * available from http://www.virtualbox.org. This file is free software;
236b2935f217749893b7034e59da3e3568928acevboxsync * you can redistribute it and/or modify it under the terms of the GNU
236b2935f217749893b7034e59da3e3568928acevboxsync * General Public License (GPL) as published by the Free Software
236b2935f217749893b7034e59da3e3568928acevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
236b2935f217749893b7034e59da3e3568928acevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
236b2935f217749893b7034e59da3e3568928acevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
236b2935f217749893b7034e59da3e3568928acevboxsync/** @page pg_gim GIM - The Guest Interface Manager
236b2935f217749893b7034e59da3e3568928acevboxsync * The Guest Interface Manager abstracts an interface provider through which
236b2935f217749893b7034e59da3e3568928acevboxsync * guests may interact with the hypervisor.
236b2935f217749893b7034e59da3e3568928acevboxsync * @see grp_gim
236b2935f217749893b7034e59da3e3568928acevboxsync * @section sec_gim_provider Providers
236b2935f217749893b7034e59da3e3568928acevboxsync * A GIM provider implements a particular hypervisor interface such as Microsoft
236b2935f217749893b7034e59da3e3568928acevboxsync * Hyper-V, Linux KVM and so on. It hooks into various components in the VMM to
157093a77f2752732368338110cb50fa6cd7717fvboxsync * ease the guest in running under a recognized, virtualized environment.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * The GIM provider configured for the VM needs to be recognized by the guest OS
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * in order to make use of features supported by the interface. Since it
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * requires co-operation from the guest OS, a GIM provider may also referred to
157093a77f2752732368338110cb50fa6cd7717fvboxsync * as a paravirtualization interface.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * One of the goals of having a paravirtualized interface is for enabling guests
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * to be more accurate and efficient when operating in a virtualized
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * environment. For instance, a guest OS which interfaces to VirtualBox through
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * a GIM provider may rely on the provider for supplying the correct TSC
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * frequency of the host processor. The guest can then avoid caliberating the
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync * TSC itself, resulting in higher accuracy and better performance.
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * At most, only one GIM provider can be active for a running VM and cannot be
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * changed during the lifetime of the VM.
236b2935f217749893b7034e59da3e3568928acevboxsync/*******************************************************************************
236b2935f217749893b7034e59da3e3568928acevboxsync* Header Files *
236b2935f217749893b7034e59da3e3568928acevboxsync*******************************************************************************/
236b2935f217749893b7034e59da3e3568928acevboxsync/* Include all GIM providers. */
236b2935f217749893b7034e59da3e3568928acevboxsync/*******************************************************************************
236b2935f217749893b7034e59da3e3568928acevboxsync* Internal Functions *
236b2935f217749893b7034e59da3e3568928acevboxsync*******************************************************************************/
236b2935f217749893b7034e59da3e3568928acevboxsyncstatic DECLCALLBACK(int) gimR3Save(PVM pVM, PSSMHANDLE pSSM);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsyncstatic DECLCALLBACK(int) gimR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion, uint32_t uPass);
236b2935f217749893b7034e59da3e3568928acevboxsync * Initializes the GIM.
236b2935f217749893b7034e59da3e3568928acevboxsync * @returns VBox status code.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param pVM Pointer to the VM.
236b2935f217749893b7034e59da3e3568928acevboxsync * Assert alignment and sizes.
236b2935f217749893b7034e59da3e3568928acevboxsync AssertCompile(sizeof(pVM->gim.s) <= sizeof(pVM->gim.padding));
236b2935f217749893b7034e59da3e3568928acevboxsync * Register the saved state data unit.
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync int rc = SSMR3RegisterInternal(pVM, "GIM", 0 /* uInstance */, GIM_SAVED_STATE_VERSION, sizeof(GIM),
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync NULL /* pfnLivePrep */, NULL /* pfnLiveExec */, NULL /* pfnLiveVote*/,
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync NULL /* pfnSavePrep */, gimR3Save, NULL /* pfnSaveDone */,
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync NULL /* pfnLoadPrep */, gimR3Load, NULL /* pfnLoadDone */);
236b2935f217749893b7034e59da3e3568928acevboxsync * Read configuration.
236b2935f217749893b7034e59da3e3568928acevboxsync PCFGMNODE pCfgNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "GIM/");
1f60035b60989886e7b26f8db14812ca63dc2acbvboxsync /** @cfgm{/GIM/Provider, string}
236b2935f217749893b7034e59da3e3568928acevboxsync * The name of the GIM provider. The default is "none". */
4ab1e1de561327173718600b82c542cbe1cc878cvboxsync rc = CFGMR3QueryStringDef(pCfgNode, "Provider", szProvider, sizeof(szProvider), "None");
1f60035b60989886e7b26f8db14812ca63dc2acbvboxsync /** @cfgm{/GIM/Version, uint32_t}
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * The interface version. The default is 0, which means "provide the most
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync * up-to-date implementation". */
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync rc = CFGMR3QueryU32Def(pCfgNode, "Version", &uVersion, 0 /* default */);
236b2935f217749893b7034e59da3e3568928acevboxsync * Setup the GIM provider for this VM.
bc5cd42756b3f98351040bbfccc08dd9bacd103avboxsync LogRel(("GIM: Using provider \"%s\" (Implementation version: %u)\n", szProvider, uVersion));
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync /** @todo r=bird: Because u32Version is saved, it should be translated to the
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync * 'most up-to-date implementation' version number when 0. Otherwise,
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync * we'll have abiguities when loading the state of older VMs. */
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync rc = VMR3SetError(pVM->pUVM, VERR_GIM_INVALID_PROVIDER, RT_SRC_POS, "Provider \"%s\" unknown.", szProvider);
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync * Initializes the remaining bits of the GIM provider.
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync * This is called after initializing HM and most other VMM components.
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync * @returns VBox status code.
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync * @param pVM Pointer to the VM.
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync * @param enmWhat What has been completed.
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync * @thread EMT(0)
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync if (!TMR3CpuTickIsFixedRateMonotonic(pVM, true /* fWithParavirtEnabled */))
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync LogRel(("GIM: Warning!!! Host TSC is unstable. The guest may behave unpredictably with a paravirtualized clock.\n"));
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync * Applies relocations to data and code managed by this component.
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync * This function will be called at init and whenever the VMM need to relocate
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync * itself inside the GC.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param pVM Pointer to the VM.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param offDelta Relocation delta relative to old location.
236b2935f217749893b7034e59da3e3568928acevboxsyncVMM_INT_DECL(void) GIMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync if ( pVM->gim.s.enmProviderId == GIMPROVIDERID_NONE
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync AssertMsgFailed(("Invalid provider Id %#x\n", pVM->gim.s.enmProviderId));
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Executes state-save operation.
236b2935f217749893b7034e59da3e3568928acevboxsync * @returns VBox status code.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param pVM Pointer to the VM.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param pSSM SSM operation handle.
236b2935f217749893b7034e59da3e3568928acevboxsyncDECLCALLBACK(int) gimR3Save(PVM pVM, PSSMHANDLE pSSM)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync /** @todo Save per-CPU data. */
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Save per-VM data.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Save provider-specific data.
236b2935f217749893b7034e59da3e3568928acevboxsync * Execute state load operation.
236b2935f217749893b7034e59da3e3568928acevboxsync * @returns VBox status code.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param pVM Pointer to the VM.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param pSSM SSM operation handle.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param uVersion Data layout version.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param uPass The data pass.
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsyncDECLCALLBACK(int) gimR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion, uint32_t uPass)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync /** @todo Load per-CPU data. */
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Load per-VM data.
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync rc = SSMR3GetU32(pSSM, &uProviderId); AssertRCReturn(rc, rc);
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync rc = SSMR3GetU32(pSSM, &uProviderVersion); AssertRCReturn(rc, rc);
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync if ((GIMPROVIDERID)uProviderId != pVM->gim.s.enmProviderId)
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Saved GIM provider %u differs from the configured one (%u)."),
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync#if 0 /** @todo r=bird: Figure out what you mean to do here with the version. */
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Saved GIM provider version %u differs from the configured one (%u)."),
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Load provider-specific data.
236b2935f217749893b7034e59da3e3568928acevboxsync * Terminates the GIM.
236b2935f217749893b7034e59da3e3568928acevboxsync * Termination means cleaning up and freeing all resources,
236b2935f217749893b7034e59da3e3568928acevboxsync * the VM itself is, at this point, powered off or suspended.
236b2935f217749893b7034e59da3e3568928acevboxsync * @returns VBox status code.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param pVM Pointer to the VM.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * The VM is being reset.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * For the GIM component this means unmapping and unregistering MMIO2 regions
157093a77f2752732368338110cb50fa6cd7717fvboxsync * and other provider-specific resets.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @returns VBox status code.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pVM Pointer to the VM.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Registers the GIM device with VMM.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pVM Pointer to the VM.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pDevIns Pointer to the GIM device instance.
157093a77f2752732368338110cb50fa6cd7717fvboxsyncVMMR3DECL(void) GIMR3GimDeviceRegister(PVM pVM, PPDMDEVINS pDevIns)
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Returns the array of MMIO2 regions that are expected to be registered and
157093a77f2752732368338110cb50fa6cd7717fvboxsync * later mapped into the guest-physical address space for the GIM provider
157093a77f2752732368338110cb50fa6cd7717fvboxsync * configured for the VM.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @returns Pointer to an array of GIM MMIO2 regions, may return NULL.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pVM Pointer to the VM.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pcRegions Where to store the number of items in the array.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @remarks The caller does not own and therefore must -NOT- try to free the
157093a77f2752732368338110cb50fa6cd7717fvboxsync * returned pointer.
157093a77f2752732368338110cb50fa6cd7717fvboxsyncVMMR3DECL(PGIMMMIO2REGION) GIMR3GetMmio2Regions(PVM pVM, uint32_t *pcRegions)
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Unmaps a registered MMIO2 region in the guest address space and removes any
157093a77f2752732368338110cb50fa6cd7717fvboxsync * access handlers for it.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @returns VBox status code.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pVM Pointer to the VM.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pRegion Pointer to the GIM MMIO2 region.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncVMMR3_INT_DECL(int) GIMR3Mmio2Unmap(PVM pVM, PGIMMMIO2REGION pRegion)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync int rc = PGMHandlerPhysicalDeregister(pVM, pRegion->GCPhysPage);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync rc = PDMDevHlpMMIO2Unmap(pDevIns, pRegion->iRegion, pRegion->GCPhysPage);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Write access handler for a mapped MMIO2 region. At present, this handler
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * simply ignores writes.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * In the future we might want to let the GIM provider decide what the handler
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * should do (like throwing #GP faults).
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @returns VBox status code.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pVM Pointer to the VM.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param GCPhys The guest-physical address of the region.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pvPhys Pointer to the region in the guest address space.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pvBuf Pointer to the data being read/written.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param cbBuf The size of the buffer in @a pvBuf.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param enmAccessType The type of access.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pvUser User argument (NULL, not used).
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncstatic DECLCALLBACK(int) gimR3Mmio2WriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Ignore writes to the mapped MMIO2 page.
157093a77f2752732368338110cb50fa6cd7717fvboxsync return VINF_SUCCESS; /** @todo Hyper-V says we should #GP(0) fault for writes to the Hypercall and TSC page. */
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Maps a registered MMIO2 region in the guest address space. The region will be
157093a77f2752732368338110cb50fa6cd7717fvboxsync * made read-only and writes from the guest will be ignored.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @returns VBox status code.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pVM Pointer to the VM.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pRegion Pointer to the GIM MMIO2 region.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param GCPhysRegion Where in the guest address space to map the region.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncVMMR3_INT_DECL(int) GIMR3Mmio2Map(PVM pVM, PGIMMMIO2REGION pRegion, RTGCPHYS GCPhysRegion)
157093a77f2752732368338110cb50fa6cd7717fvboxsync /* The guest-physical address must be page-aligned. */
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync LogFunc(("%s: %#RGp not paging aligned\n", pRegion->szDescription, GCPhysRegion));
157093a77f2752732368338110cb50fa6cd7717fvboxsync /* Allow only normal pages to be overlaid using our MMIO2 pages (disallow MMIO, ROM, reserved pages). */
157093a77f2752732368338110cb50fa6cd7717fvboxsync /** @todo Hyper-V doesn't seem to be very strict about this, may be relax
157093a77f2752732368338110cb50fa6cd7717fvboxsync * later if some guest really requires it. */
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync LogFunc(("%s: %#RGp is not normal memory\n", pRegion->szDescription, GCPhysRegion));
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync LogFunc(("%s: Region has not been registered.\n"));
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Map the MMIO2 region over the specified guest-physical address.
157093a77f2752732368338110cb50fa6cd7717fvboxsync int rc = PDMDevHlpMMIO2Map(pDevIns, pRegion->iRegion, GCPhysRegion);
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Install access-handlers for the mapped page to prevent (ignore) writes to it from the guest.
157093a77f2752732368338110cb50fa6cd7717fvboxsync GCPhysRegion, GCPhysRegion + (pRegion->cbRegion - 1),
157093a77f2752732368338110cb50fa6cd7717fvboxsync NULL /* pszModR0 */, NULL /* pszHandlerR0 */, NIL_RTR0PTR /* pvUserR0 */,
157093a77f2752732368338110cb50fa6cd7717fvboxsync NULL /* pszModRC */, NULL /* pszHandlerRC */, NIL_RTRCPTR /* pvUserRC */,
157093a77f2752732368338110cb50fa6cd7717fvboxsync PDMDevHlpMMIO2Unmap(pDevIns, pRegion->iRegion, GCPhysRegion);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Registers the physical handler for the registered and mapped MMIO2 region.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @returns VBox status code.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pVM Pointer to the VM.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pRegion Pointer to the GIM MMIO2 region.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncVMMR3_INT_DECL(int) GIMR3Mmio2HandlerPhysicalRegister(PVM pVM, PGIMMMIO2REGION pRegion)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync AssertReturn(pRegion->fRegistered, VERR_GIM_IPE_2);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync pRegion->GCPhysPage, pRegion->GCPhysPage + (pRegion->cbRegion - 1),
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync NULL /* pszModR0 */, NULL /* pszHandlerR0 */, NIL_RTR0PTR /* pvUserR0 */,
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync NULL /* pszModRC */, NULL /* pszHandlerRC */, NIL_RTRCPTR /* pvUserRC */,
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Deregisters the physical handler for the MMIO2 region.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @returns VBox status code.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pVM Pointer to the VM.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pRegion Pointer to the GIM MMIO2 region.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncVMMR3_INT_DECL(int) GIMR3Mmio2HandlerPhysicalDeregister(PVM pVM, PGIMMMIO2REGION pRegion)