GIM.cpp revision 8d9e0655efb148a5dd672705e315de97a1ad12f1
/* $Id$ */
/** @file
* GIM - Guest Interface Manager.
*/
/*
* Copyright (C) 2014 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/** @page pg_gim GIM - The Guest Interface Manager
*
* The Guest Interface Manager abstracts an interface provider through which
* guests may interact with the hypervisor.
*
* @see grp_gim
*
*
* @section sec_gim_provider Providers
*
* A GIM provider implements a particular hypervisor interface such as Microsoft
* Hyper-V, Linux KVM and so on. It hooks into various components in the VMM to
* ease the guest in running under a recognized, virtualized environment.
*
* If the GIM provider configured for the VM needs to be recognized by the guest
* OS inorder to make use of features supported by the interface. Since it
* requires co-operation from the guest OS, a GIM provider is also referred to
* as a paravirtualization interface.
*
* One of the ideas behind this, is primarily for making guests more accurate
* and efficient when operating in a virtualized environment. For instance, a
* guest OS which interfaces to VirtualBox through a GIM provider may rely on
* the provider (and VirtualBox ultimately) for providing the correct TSC
* frequency of the host processor and may therefore not have to caliberate the
* TSC itself, resulting in higher accuracy and saving several CPU cycles.
*
* At most, only one GIM provider can be active for a running VM and cannot be
* changed during the lifetime of the VM.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_GIM
#include "GIMInternal.h"
/* Include all GIM providers. */
#include "GIMMinimalInternal.h"
#include "GIMHvInternal.h"
/*******************************************************************************
* Internal Functions *
*******************************************************************************/
/**
* Initializes the GIM.
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
*/
{
LogFlow(("GIMR3Init\n"));
/*
* Assert alignment and sizes.
*/
/*
* Register the saved state data unit.
*/
int rc;
if (RT_FAILURE(rc))
return rc;
/*
* Read configuration.
*/
* The name of the GIM provider. The default is "none". */
char szProvider[64];
* The interface version. The default is 0, which means "provide the most
* up-to-date implementation". */
/*
* Setup the GIM provider for this VM.
*/
{
}
else
{
{
}
{
}
/** @todo KVM and others. */
else
{
}
}
return rc;
}
{
LogFlow(("GIMR3InitFinalize\n"));
return VINF_SUCCESS;
int rc = VINF_SUCCESS;
{
case GIMPROVIDERID_MINIMAL:
{
break;
}
default:
break;
}
return rc;
}
/**
* Applies relocations to data and code managed by this component. This function
* will be called at init and whenever the VMM need to relocate itself inside
* the GC.
*
* @param pVM Pointer to the VM.
* @param offDelta Relocation delta relative to old location.
*/
{
LogFlow(("GIMR3Relocate\n"));
|| HMIsEnabled(pVM))
{
return;
}
{
case GIMPROVIDERID_MINIMAL:
{
break;
}
case GIMPROVIDERID_HYPERV:
{
break;
}
case GIMPROVIDERID_KVM: /** @todo KVM. */
default:
{
break;
}
}
}
/**
* Executes state-save operation.
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
* @param pSSM SSM operation handle.
*/
{
/** @todo Save per-CPU data. */
int rc;
#if 0
{
}
#endif
/*
* Save per-VM data.
*/
/*
* Save provider-specific data.
*/
{
{
case GIMPROVIDERID_HYPERV:
break;
default:
break;
}
}
return rc;
}
/**
* Execute state load operation.
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
* @param pSSM SSM operation handle.
* @param uVersion Data layout version.
* @param uPass The data pass.
*/
{
if (uPass != SSM_PASS_FINAL)
return VINF_SUCCESS;
/** @todo Load per-CPU data. */
int rc;
#if 0
{
}
#endif
/*
* Load per-VM data.
*/
/*
* Load provider-specific data.
*/
{
{
case GIMPROVIDERID_HYPERV:
break;
default:
break;
}
}
return rc;
}
/**
* Terminates the GIM.
*
* Termination means cleaning up and freeing all resources,
* the VM itself is, at this point, powered off or suspended.
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
*/
{
return VINF_SUCCESS;
{
case GIMPROVIDERID_HYPERV:
return GIMR3HvTerm(pVM);
default:
break;
}
return VINF_SUCCESS;
}
/**
* The VM is being reset.
*
* For the GIM component this means unmapping and unregistering MMIO2 regions
* and other provider-specific resets.
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
*/
{
return;
{
case GIMPROVIDERID_HYPERV:
return GIMR3HvReset(pVM);
default:
break;
}
}
/**
* Registers the GIM device with VMM.
*
* @param pVM Pointer to the VM.
* @param pDevIns Pointer to the GIM device instance.
*/
{
}
/**
* Returns the array of MMIO2 regions that are expected to be registered and
* later mapped into the guest-physical address space for the GIM provider
* configured for the VM.
*
* @returns Pointer to an array of GIM MMIO2 regions, may return NULL.
* @param pVM Pointer to the VM.
* @param pcRegions Where to store the number of items in the array.
*
* @remarks The caller does not own and therefore must -NOT- try to free the
* returned pointer.
*/
{
*pcRegions = 0;
return NULL;
{
case GIMPROVIDERID_HYPERV:
case GIMPROVIDERID_KVM: /** @todo KVM. */
default:
break;
}
return NULL;
}
/**
* Unmaps a registered MMIO2 region in the guest address space and removes any
* access handlers for it.
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
* @param pRegion Pointer to the GIM MMIO2 region.
*/
{
{
if (RT_SUCCESS(rc))
{
}
}
return VINF_SUCCESS;
}
/**
* Write access handler for a mapped MMIO2 region. At present, this handler
* simply ignores writes.
*
* In the future we might want to let the GIM provider decide what the handler
* should do (like throwing #GP faults).
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
* @param GCPhys The guest-physical address of the region.
* @param pvPhys Pointer to the region in the guest address space.
* @param cbBuf The size of the buffer in @a pvBuf.
* @param enmAccessType The type of access.
* @param pvUser User argument (NULL, not used).
*/
static DECLCALLBACK(int) gimR3Mmio2WriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
{
/*
* Ignore writes to the mapped MMIO2 page.
*/
return VINF_SUCCESS; /** @todo Hyper-V says we should #GP(0) fault for writes to the Hypercall and TSC page. */
}
/**
* Maps a registered MMIO2 region in the guest address space. The region will be
* made read-only and writes from the guest will be ignored.
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
* @param pRegion Pointer to the GIM MMIO2 region.
* @param GCPhysRegion Where in the guest address space to map the region.
*/
{
/* The guest-physical address must be page-aligned. */
if (GCPhysRegion & PAGE_OFFSET_MASK)
{
}
/* Allow only normal pages to be overlaid using our MMIO2 pages (disallow MMIO, ROM, reserved pages). */
/** @todo Hyper-V doesn't seem to be very strict about this, may be relax
* later if some guest really requires it. */
{
}
if (!pRegion->fRegistered)
{
LogFunc(("%s: Region has not been registered.\n"));
return VERR_GIM_IPE_1;
}
/*
* Map the MMIO2 region over the specified guest-physical address.
*/
if (RT_SUCCESS(rc))
{
/*
* Install access-handlers for the mapped page to prevent (ignore) writes to it from the guest.
*/
if (RT_SUCCESS(rc))
{
return rc;
}
}
return rc;
}
#if 0
/**
* Registers the physical handler for the registered and mapped MMIO2 region.
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
* @param pRegion Pointer to the GIM MMIO2 region.
*/
{
return PGMR3HandlerPhysicalRegister(pVM,
}
/**
* Deregisters the physical handler for the MMIO2 region.
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
* @param pRegion Pointer to the GIM MMIO2 region.
*/
{
}
#endif