GIM.cpp revision 0bc35f54322c5f9b2d43b064f839a8cf8c99a234
ece9652d971886b99a269656ea4782319637e75avboxsync * GIM - Guest Interface Manager.
e64031e20c39650a7bc902a3e1aba613b9415deevboxsync * Copyright (C) 2014-2015 Oracle Corporation
ece9652d971886b99a269656ea4782319637e75avboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
ece9652d971886b99a269656ea4782319637e75avboxsync * available from http://www.virtualbox.org. This file is free software;
ece9652d971886b99a269656ea4782319637e75avboxsync * you can redistribute it and/or modify it under the terms of the GNU
ece9652d971886b99a269656ea4782319637e75avboxsync * General Public License (GPL) as published by the Free Software
ece9652d971886b99a269656ea4782319637e75avboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
ece9652d971886b99a269656ea4782319637e75avboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
ece9652d971886b99a269656ea4782319637e75avboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
ece9652d971886b99a269656ea4782319637e75avboxsync/** @page pg_gim GIM - The Guest Interface Manager
ece9652d971886b99a269656ea4782319637e75avboxsync * The Guest Interface Manager abstracts an interface provider through which
ece9652d971886b99a269656ea4782319637e75avboxsync * guests may interact with the hypervisor.
ece9652d971886b99a269656ea4782319637e75avboxsync * @see grp_gim
ece9652d971886b99a269656ea4782319637e75avboxsync * @section sec_gim_provider Providers
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * A GIM provider implements a particular hypervisor interface such as Microsoft
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * Hyper-V, Linux KVM and so on. It hooks into various components in the VMM to
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync * ease the guest in running under a recognized, virtualized environment.
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync * The GIM provider configured for the VM needs to be recognized by the guest OS
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync * in order to make use of features supported by the interface. Since it
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync * requires co-operation from the guest OS, a GIM provider may also referred to
aafe9fe588edab292546a0e4c1f7eb377fd35df4vboxsync * as a paravirtualization interface.
aafe9fe588edab292546a0e4c1f7eb377fd35df4vboxsync * One of the goals of having a paravirtualized interface is for enabling guests
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * to be more accurate and efficient when operating in a virtualized
47c2a6d84685d16b7ef87c307331e5588d892ef0vboxsync * environment. For instance, a guest OS which interfaces to VirtualBox through
47c2a6d84685d16b7ef87c307331e5588d892ef0vboxsync * a GIM provider may rely on the provider for supplying the correct TSC
47c2a6d84685d16b7ef87c307331e5588d892ef0vboxsync * frequency of the host processor. The guest can then avoid caliberating the
47c2a6d84685d16b7ef87c307331e5588d892ef0vboxsync * TSC itself, resulting in higher accuracy and better performance.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * At most, only one GIM provider can be active for a running VM and cannot be
47c2a6d84685d16b7ef87c307331e5588d892ef0vboxsync * changed during the lifetime of the VM.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync/*******************************************************************************
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync* Header Files *
83365ff77c1571f994b3a15bfbdee077d2ea8a07vboxsync*******************************************************************************/
b09004e17d8096e3983fb0ecf5aad272877037ccvboxsync/* Include all GIM providers. */
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync/*******************************************************************************
b09004e17d8096e3983fb0ecf5aad272877037ccvboxsync* Internal Functions *
b09004e17d8096e3983fb0ecf5aad272877037ccvboxsync*******************************************************************************/
992ef02987d71b2b9f73a50265997c7f8e384886vboxsyncstatic DECLCALLBACK(int) gimR3Save(PVM pVM, PSSMHANDLE pSSM);
992ef02987d71b2b9f73a50265997c7f8e384886vboxsyncstatic DECLCALLBACK(int) gimR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion, uint32_t uPass);
1c19381e9455f78f30a14a20d19f1dab7da19334vboxsync * Initializes the GIM.
ece9652d971886b99a269656ea4782319637e75avboxsync * @returns VBox status code.
ece9652d971886b99a269656ea4782319637e75avboxsync * @param pVM Pointer to the VM.
e7f5b62e52275099a4d14501306063e23876b771vboxsync * Assert alignment and sizes.
ece9652d971886b99a269656ea4782319637e75avboxsync AssertCompile(sizeof(pVM->gim.s) <= sizeof(pVM->gim.padding));
e7f5b62e52275099a4d14501306063e23876b771vboxsync * Register the saved state data unit.
e7f5b62e52275099a4d14501306063e23876b771vboxsync int rc = SSMR3RegisterInternal(pVM, "GIM", 0 /* uInstance */, GIM_SAVED_STATE_VERSION, sizeof(GIM),
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync NULL /* pfnLivePrep */, NULL /* pfnLiveExec */, NULL /* pfnLiveVote*/,
ece9652d971886b99a269656ea4782319637e75avboxsync NULL /* pfnSavePrep */, gimR3Save, NULL /* pfnSaveDone */,
ece9652d971886b99a269656ea4782319637e75avboxsync NULL /* pfnLoadPrep */, gimR3Load, NULL /* pfnLoadDone */);
ece9652d971886b99a269656ea4782319637e75avboxsync * Read configuration.
ece9652d971886b99a269656ea4782319637e75avboxsync PCFGMNODE pCfgNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "GIM/");
ece9652d971886b99a269656ea4782319637e75avboxsync /** @cfgm{/GIM/Provider, string}
ece9652d971886b99a269656ea4782319637e75avboxsync * The name of the GIM provider. The default is "none". */
e7f5b62e52275099a4d14501306063e23876b771vboxsync rc = CFGMR3QueryStringDef(pCfgNode, "Provider", szProvider, sizeof(szProvider), "None");
ece9652d971886b99a269656ea4782319637e75avboxsync /** @cfgm{/GIM/Version, uint32_t}
ece9652d971886b99a269656ea4782319637e75avboxsync * The interface version. The default is 0, which means "provide the most
ece9652d971886b99a269656ea4782319637e75avboxsync * up-to-date implementation". */
ece9652d971886b99a269656ea4782319637e75avboxsync rc = CFGMR3QueryU32Def(pCfgNode, "Version", &uVersion, 0 /* default */);
0be1c98f1388ddc063a7e830f53e2018f658b348vboxsync * Setup the GIM provider for this VM.
f910333674d7dd65ca746ec010ef354fd239cea4vboxsync LogRel(("GIM: Using provider \"%s\" (Implementation version: %u)\n", szProvider, uVersion));
f8c709737db3e0499abab64fc2ff79df9a80d200vboxsync /** @todo r=bird: Because u32Version is saved, it should be translated to the
f910333674d7dd65ca746ec010ef354fd239cea4vboxsync * 'most up-to-date implementation' version number when 0. Otherwise,
e7f5b62e52275099a4d14501306063e23876b771vboxsync * we'll have abiguities when loading the state of older VMs. */
f910333674d7dd65ca746ec010ef354fd239cea4vboxsync /** @todo KVM and others. */
f910333674d7dd65ca746ec010ef354fd239cea4vboxsync rc = VMR3SetError(pVM->pUVM, VERR_GIM_INVALID_PROVIDER, RT_SRC_POS, "Provider \"%s\" unknown.", szProvider);
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync * Initializes the remaining bits of the GIM provider.
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync * This is called after initializing HM and most other VMM components.
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync * @returns VBox status code.
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync * @param pVM Pointer to the VM.
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync * @param enmWhat What has been completed.
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync * @thread EMT(0)
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync if (!TMR3CpuTickIsFixedRateMonotonic(pVM, true /* fWithParavirtEnabled */))
6cb1a01aaf746e26c5190a7b0fca706393bdf3aevboxsync LogRel(("GIM: Warning!!! Host TSC is unstable. The guest may behave unpredictably with a paravirtualized clock.\n"));
e7f5b62e52275099a4d14501306063e23876b771vboxsync * Applies relocations to data and code managed by this component.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * This function will be called at init and whenever the VMM need to relocate
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * itself inside the GC.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * @param pVM Pointer to the VM.
599595881adeaefb423b996cf29e21e5831c26d7vboxsync * @param offDelta Relocation delta relative to old location.
599595881adeaefb423b996cf29e21e5831c26d7vboxsyncVMM_INT_DECL(void) GIMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync if ( pVM->gim.s.enmProviderId == GIMPROVIDERID_NONE
e5ffd0945e1eb5f641e513f84cfce9870e2d4e48vboxsync AssertMsgFailed(("Invalid provider Id %#x\n", pVM->gim.s.enmProviderId));
e5ffd0945e1eb5f641e513f84cfce9870e2d4e48vboxsync * Executes state-save operation.
e5ffd0945e1eb5f641e513f84cfce9870e2d4e48vboxsync * @returns VBox status code.
ece9652d971886b99a269656ea4782319637e75avboxsync * @param pVM Pointer to the VM.
ece9652d971886b99a269656ea4782319637e75avboxsync * @param pSSM SSM operation handle.
b09004e17d8096e3983fb0ecf5aad272877037ccvboxsyncDECLCALLBACK(int) gimR3Save(PVM pVM, PSSMHANDLE pSSM)
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync /** @todo Save per-CPU data. */
ece9652d971886b99a269656ea4782319637e75avboxsync * Save per-VM data.
e7f5b62e52275099a4d14501306063e23876b771vboxsync * Save provider-specific data.
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync * Execute state load operation.
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync * @returns VBox status code.
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync * @param pVM Pointer to the VM.
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync * @param pSSM SSM operation handle.
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync * @param uVersion Data layout version.
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync * @param uPass The data pass.
e35d51bc86d234abdf08fe247ea901501faa022fvboxsyncDECLCALLBACK(int) gimR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion, uint32_t uPass)
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync /** @todo Load per-CPU data. */
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync * Load per-VM data.
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync rc = SSMR3GetU32(pSSM, &uProviderId); AssertRCReturn(rc, rc);
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync rc = SSMR3GetU32(pSSM, &uProviderVersion); AssertRCReturn(rc, rc);
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync if ((GIMPROVIDERID)uProviderId != pVM->gim.s.enmProviderId)
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Saved GIM provider %u differs from the configured one (%u)."),
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync#if 0 /** @todo r=bird: Figure out what you mean to do here with the version. */
e35d51bc86d234abdf08fe247ea901501faa022fvboxsync return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Saved GIM provider version %u differs from the configured one (%u)."),
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * Load provider-specific data.
b09004e17d8096e3983fb0ecf5aad272877037ccvboxsync * Terminates the GIM.
b09004e17d8096e3983fb0ecf5aad272877037ccvboxsync * Termination means cleaning up and freeing all resources,
b09004e17d8096e3983fb0ecf5aad272877037ccvboxsync * the VM itself is, at this point, powered off or suspended.
36ec4b6f42e209d010ade084a96f46ce763345eavboxsync * @returns VBox status code.
b09004e17d8096e3983fb0ecf5aad272877037ccvboxsync * @param pVM Pointer to the VM.
ece9652d971886b99a269656ea4782319637e75avboxsync * The VM is being reset.
e5ffd0945e1eb5f641e513f84cfce9870e2d4e48vboxsync * For the GIM component this means unmapping and unregistering MMIO2 regions
e5ffd0945e1eb5f641e513f84cfce9870e2d4e48vboxsync * and other provider-specific resets.
e5ffd0945e1eb5f641e513f84cfce9870e2d4e48vboxsync * @returns VBox status code.
ece9652d971886b99a269656ea4782319637e75avboxsync * @param pVM Pointer to the VM.
e7f5b62e52275099a4d14501306063e23876b771vboxsync * Registers the GIM device with VMM.
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync * @param pVM Pointer to the VM.
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync * @param pDevIns Pointer to the GIM device instance.
b09004e17d8096e3983fb0ecf5aad272877037ccvboxsyncVMMR3DECL(void) GIMR3GimDeviceRegister(PVM pVM, PPDMDEVINS pDevIns)
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync * Returns the array of MMIO2 regions that are expected to be registered and
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync * later mapped into the guest-physical address space for the GIM provider
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync * configured for the VM.
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync * @returns Pointer to an array of GIM MMIO2 regions, may return NULL.
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync * @param pVM Pointer to the VM.
b09004e17d8096e3983fb0ecf5aad272877037ccvboxsync * @param pcRegions Where to store the number of items in the array.
992ef02987d71b2b9f73a50265997c7f8e384886vboxsync * @remarks The caller does not own and therefore must -NOT- try to free the
b09004e17d8096e3983fb0ecf5aad272877037ccvboxsync * returned pointer.
b09004e17d8096e3983fb0ecf5aad272877037ccvboxsyncVMMR3DECL(PGIMMMIO2REGION) GIMR3GetMmio2Regions(PVM pVM, uint32_t *pcRegions)
return NULL;
return VINF_SUCCESS;
static DECLCALLBACK(int) gimR3Mmio2WriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
return VINF_SUCCESS; /** @todo Hyper-V says we should #GP(0) fault for writes to the Hypercall and TSC page. */
/* Allow only normal pages to be overlaid using our MMIO2 pages (disallow MMIO, ROM, reserved pages). */
return VERR_GIM_IPE_1;
return rc;
return rc;