236b2935f217749893b7034e59da3e3568928acevboxsync/* $Id$ */
236b2935f217749893b7034e59da3e3568928acevboxsync/** @file
236b2935f217749893b7034e59da3e3568928acevboxsync * GIM - Guest Interface Manager.
236b2935f217749893b7034e59da3e3568928acevboxsync */
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync/*
aa7f783d8893b6004cb8d993273c008944f81544vboxsync * Copyright (C) 2014-2015 Oracle Corporation
236b2935f217749893b7034e59da3e3568928acevboxsync *
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 */
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync/** @page pg_gim GIM - The Guest Interface Manager
236b2935f217749893b7034e59da3e3568928acevboxsync *
236b2935f217749893b7034e59da3e3568928acevboxsync * The Guest Interface Manager abstracts an interface provider through which
236b2935f217749893b7034e59da3e3568928acevboxsync * guests may interact with the hypervisor.
236b2935f217749893b7034e59da3e3568928acevboxsync *
236b2935f217749893b7034e59da3e3568928acevboxsync * @see grp_gim
236b2935f217749893b7034e59da3e3568928acevboxsync *
236b2935f217749893b7034e59da3e3568928acevboxsync *
236b2935f217749893b7034e59da3e3568928acevboxsync * @section sec_gim_provider Providers
236b2935f217749893b7034e59da3e3568928acevboxsync *
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.
236b2935f217749893b7034e59da3e3568928acevboxsync *
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.
236b2935f217749893b7034e59da3e3568928acevboxsync *
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.
236b2935f217749893b7034e59da3e3568928acevboxsync *
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
236b2935f217749893b7034e59da3e3568928acevboxsync/*******************************************************************************
236b2935f217749893b7034e59da3e3568928acevboxsync* Header Files *
236b2935f217749893b7034e59da3e3568928acevboxsync*******************************************************************************/
236b2935f217749893b7034e59da3e3568928acevboxsync#define LOG_GROUP LOG_GROUP_GIM
236b2935f217749893b7034e59da3e3568928acevboxsync#include <VBox/log.h>
236b2935f217749893b7034e59da3e3568928acevboxsync#include "GIMInternal.h"
236b2935f217749893b7034e59da3e3568928acevboxsync#include <VBox/vmm/vm.h>
236b2935f217749893b7034e59da3e3568928acevboxsync#include <VBox/vmm/hm.h>
236b2935f217749893b7034e59da3e3568928acevboxsync#include <VBox/vmm/ssm.h>
157093a77f2752732368338110cb50fa6cd7717fvboxsync#include <VBox/vmm/pdmdev.h>
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync#include <iprt/err.h>
236b2935f217749893b7034e59da3e3568928acevboxsync#include <iprt/string.h>
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync/* Include all GIM providers. */
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync#include "GIMMinimalInternal.h"
236b2935f217749893b7034e59da3e3568928acevboxsync#include "GIMHvInternal.h"
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync#include "GIMKvmInternal.h"
236b2935f217749893b7034e59da3e3568928acevboxsync
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
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync/**
236b2935f217749893b7034e59da3e3568928acevboxsync * Initializes the GIM.
236b2935f217749893b7034e59da3e3568928acevboxsync *
236b2935f217749893b7034e59da3e3568928acevboxsync * @returns VBox status code.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param pVM Pointer to the VM.
236b2935f217749893b7034e59da3e3568928acevboxsync */
236b2935f217749893b7034e59da3e3568928acevboxsyncVMMR3_INT_DECL(int) GIMR3Init(PVM pVM)
236b2935f217749893b7034e59da3e3568928acevboxsync{
236b2935f217749893b7034e59da3e3568928acevboxsync LogFlow(("GIMR3Init\n"));
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync /*
236b2935f217749893b7034e59da3e3568928acevboxsync * Assert alignment and sizes.
236b2935f217749893b7034e59da3e3568928acevboxsync */
236b2935f217749893b7034e59da3e3568928acevboxsync AssertCompile(sizeof(pVM->gim.s) <= sizeof(pVM->gim.padding));
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync /*
236b2935f217749893b7034e59da3e3568928acevboxsync * Register the saved state data unit.
236b2935f217749893b7034e59da3e3568928acevboxsync */
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 if (RT_FAILURE(rc))
236b2935f217749893b7034e59da3e3568928acevboxsync return rc;
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync /*
236b2935f217749893b7034e59da3e3568928acevboxsync * Read configuration.
236b2935f217749893b7034e59da3e3568928acevboxsync */
236b2935f217749893b7034e59da3e3568928acevboxsync PCFGMNODE pCfgNode = CFGMR3GetChild(CFGMR3GetRoot(pVM), "GIM/");
236b2935f217749893b7034e59da3e3568928acevboxsync
1f60035b60989886e7b26f8db14812ca63dc2acbvboxsync /** @cfgm{/GIM/Provider, string}
236b2935f217749893b7034e59da3e3568928acevboxsync * The name of the GIM provider. The default is "none". */
236b2935f217749893b7034e59da3e3568928acevboxsync char szProvider[64];
4ab1e1de561327173718600b82c542cbe1cc878cvboxsync rc = CFGMR3QueryStringDef(pCfgNode, "Provider", szProvider, sizeof(szProvider), "None");
236b2935f217749893b7034e59da3e3568928acevboxsync AssertLogRelRCReturn(rc, rc);
236b2935f217749893b7034e59da3e3568928acevboxsync
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 uint32_t uVersion;
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync rc = CFGMR3QueryU32Def(pCfgNode, "Version", &uVersion, 0 /* default */);
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync AssertLogRelRCReturn(rc, rc);
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync /*
236b2935f217749893b7034e59da3e3568928acevboxsync * Setup the GIM provider for this VM.
236b2935f217749893b7034e59da3e3568928acevboxsync */
bc5cd42756b3f98351040bbfccc08dd9bacd103avboxsync LogRel(("GIM: Using provider \"%s\" (Implementation version: %u)\n", szProvider, uVersion));
4ab1e1de561327173718600b82c542cbe1cc878cvboxsync if (!RTStrCmp(szProvider, "None"))
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync pVM->gim.s.enmProviderId = GIMPROVIDERID_NONE;
236b2935f217749893b7034e59da3e3568928acevboxsync else
236b2935f217749893b7034e59da3e3568928acevboxsync {
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync pVM->gim.s.u32Version = 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. */
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync if (!RTStrCmp(szProvider, "Minimal"))
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync {
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync pVM->gim.s.enmProviderId = GIMPROVIDERID_MINIMAL;
f84ab9e4599e758ec1f36479f871b3f5b7f271f2vboxsync rc = gimR3MinimalInit(pVM);
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync }
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync else if (!RTStrCmp(szProvider, "HyperV"))
236b2935f217749893b7034e59da3e3568928acevboxsync {
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync pVM->gim.s.enmProviderId = GIMPROVIDERID_HYPERV;
f84ab9e4599e758ec1f36479f871b3f5b7f271f2vboxsync rc = gimR3HvInit(pVM);
236b2935f217749893b7034e59da3e3568928acevboxsync }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync else if (!RTStrCmp(szProvider, "KVM"))
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync {
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync pVM->gim.s.enmProviderId = GIMPROVIDERID_KVM;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync rc = gimR3KvmInit(pVM);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync }
236b2935f217749893b7034e59da3e3568928acevboxsync else
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync rc = VMR3SetError(pVM->pUVM, VERR_GIM_INVALID_PROVIDER, RT_SRC_POS, "Provider \"%s\" unknown.", szProvider);
236b2935f217749893b7034e59da3e3568928acevboxsync }
236b2935f217749893b7034e59da3e3568928acevboxsync return rc;
236b2935f217749893b7034e59da3e3568928acevboxsync}
236b2935f217749893b7034e59da3e3568928acevboxsync
8d9e0655efb148a5dd672705e315de97a1ad12f1vboxsync
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync/**
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync * Initializes the remaining bits of the GIM provider.
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync *
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync * This is called after initializing HM and most other VMM components.
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync *
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync * @returns VBox status code.
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync * @param pVM Pointer to the VM.
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync * @param enmWhat What has been completed.
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync * @thread EMT(0)
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync */
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsyncVMMR3_INT_DECL(int) GIMR3InitCompleted(PVM pVM)
157093a77f2752732368338110cb50fa6cd7717fvboxsync{
157093a77f2752732368338110cb50fa6cd7717fvboxsync switch (pVM->gim.s.enmProviderId)
157093a77f2752732368338110cb50fa6cd7717fvboxsync {
157093a77f2752732368338110cb50fa6cd7717fvboxsync case GIMPROVIDERID_MINIMAL:
f84ab9e4599e758ec1f36479f871b3f5b7f271f2vboxsync return gimR3MinimalInitCompleted(pVM);
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync case GIMPROVIDERID_HYPERV:
f84ab9e4599e758ec1f36479f871b3f5b7f271f2vboxsync return gimR3HvInitCompleted(pVM);
157093a77f2752732368338110cb50fa6cd7717fvboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync case GIMPROVIDERID_KVM:
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync return gimR3KvmInitCompleted(pVM);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync default:
157093a77f2752732368338110cb50fa6cd7717fvboxsync break;
157093a77f2752732368338110cb50fa6cd7717fvboxsync }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync if (!TMR3CpuTickIsFixedRateMonotonic(pVM, true /* fWithParavirtEnabled */))
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync LogRel(("GIM: Warning!!! Host TSC is unstable. The guest may behave unpredictably with a paravirtualized clock.\n"));
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
bb50cfa1b9de06edfb8d96f8d47dbd5394fb4ce3vboxsync return VINF_SUCCESS;
157093a77f2752732368338110cb50fa6cd7717fvboxsync}
157093a77f2752732368338110cb50fa6cd7717fvboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync/**
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync * Applies relocations to data and code managed by this component.
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync *
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync * This function will be called at init and whenever the VMM need to relocate
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync * itself inside the GC.
236b2935f217749893b7034e59da3e3568928acevboxsync *
236b2935f217749893b7034e59da3e3568928acevboxsync * @param pVM Pointer to the VM.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param offDelta Relocation delta relative to old location.
236b2935f217749893b7034e59da3e3568928acevboxsync */
236b2935f217749893b7034e59da3e3568928acevboxsyncVMM_INT_DECL(void) GIMR3Relocate(PVM pVM, RTGCINTPTR offDelta)
236b2935f217749893b7034e59da3e3568928acevboxsync{
236b2935f217749893b7034e59da3e3568928acevboxsync LogFlow(("GIMR3Relocate\n"));
236b2935f217749893b7034e59da3e3568928acevboxsync
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync if ( pVM->gim.s.enmProviderId == GIMPROVIDERID_NONE
236b2935f217749893b7034e59da3e3568928acevboxsync || HMIsEnabled(pVM))
236b2935f217749893b7034e59da3e3568928acevboxsync return;
236b2935f217749893b7034e59da3e3568928acevboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync switch (pVM->gim.s.enmProviderId)
236b2935f217749893b7034e59da3e3568928acevboxsync {
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync case GIMPROVIDERID_MINIMAL:
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync {
f84ab9e4599e758ec1f36479f871b3f5b7f271f2vboxsync gimR3MinimalRelocate(pVM, offDelta);
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync break;
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync }
3357df142080b5abd7a5da3358371ce0bff34e91vboxsync
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync case GIMPROVIDERID_HYPERV:
236b2935f217749893b7034e59da3e3568928acevboxsync {
f84ab9e4599e758ec1f36479f871b3f5b7f271f2vboxsync gimR3HvRelocate(pVM, offDelta);
236b2935f217749893b7034e59da3e3568928acevboxsync break;
236b2935f217749893b7034e59da3e3568928acevboxsync }
236b2935f217749893b7034e59da3e3568928acevboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync case GIMPROVIDERID_KVM:
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync {
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync gimR3KvmRelocate(pVM, offDelta);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync break;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync }
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync default:
236b2935f217749893b7034e59da3e3568928acevboxsync {
5067a9619d7131c54d4ebb371d9dac91abdd34f6vboxsync AssertMsgFailed(("Invalid provider Id %#x\n", pVM->gim.s.enmProviderId));
236b2935f217749893b7034e59da3e3568928acevboxsync break;
236b2935f217749893b7034e59da3e3568928acevboxsync }
236b2935f217749893b7034e59da3e3568928acevboxsync }
236b2935f217749893b7034e59da3e3568928acevboxsync}
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync/**
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Executes state-save operation.
236b2935f217749893b7034e59da3e3568928acevboxsync *
236b2935f217749893b7034e59da3e3568928acevboxsync * @returns VBox status code.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param pVM Pointer to the VM.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param pSSM SSM operation handle.
236b2935f217749893b7034e59da3e3568928acevboxsync */
236b2935f217749893b7034e59da3e3568928acevboxsyncDECLCALLBACK(int) gimR3Save(PVM pVM, PSSMHANDLE pSSM)
236b2935f217749893b7034e59da3e3568928acevboxsync{
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync AssertReturn(pVM, VERR_INVALID_PARAMETER);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync AssertReturn(pSSM, VERR_SSM_INVALID_STATE);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync /** @todo Save per-CPU data. */
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync int rc = VINF_SUCCESS;
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync#if 0
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync SSMR3PutU32(pSSM, pVM->cCpus);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync for (VMCPUID i = 0; i < pVM->cCpus; i++)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync {
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync rc = SSMR3PutXYZ(pSSM, pVM->aCpus[i].gim.s.XYZ);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync }
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync#endif
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync /*
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Save per-VM data.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync */
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync SSMR3PutU32(pSSM, pVM->gim.s.enmProviderId);
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync SSMR3PutU32(pSSM, pVM->gim.s.u32Version);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync /*
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Save provider-specific data.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync */
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync switch (pVM->gim.s.enmProviderId)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync {
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync case GIMPROVIDERID_HYPERV:
f84ab9e4599e758ec1f36479f871b3f5b7f271f2vboxsync rc = gimR3HvSave(pVM, pSSM);
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync AssertRCReturn(rc, rc);
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync break;
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync case GIMPROVIDERID_KVM:
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync rc = gimR3KvmSave(pVM, pSSM);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync AssertRCReturn(rc, rc);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync break;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync default:
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync break;
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync }
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync return rc;
236b2935f217749893b7034e59da3e3568928acevboxsync}
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync/**
236b2935f217749893b7034e59da3e3568928acevboxsync * Execute state load operation.
236b2935f217749893b7034e59da3e3568928acevboxsync *
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.
236b2935f217749893b7034e59da3e3568928acevboxsync */
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsyncDECLCALLBACK(int) gimR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t uSSMVersion, uint32_t uPass)
236b2935f217749893b7034e59da3e3568928acevboxsync{
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync if (uPass != SSM_PASS_FINAL)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync return VINF_SUCCESS;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync if (uSSMVersion != GIM_SAVED_STATE_VERSION)
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync return VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION;
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync /** @todo Load per-CPU data. */
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync int rc;
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync#if 0
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync for (VMCPUID i = 0; i < pVM->cCpus; i++)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync {
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync rc = SSMR3PutXYZ(pSSM, pVM->aCpus[i].gim.s.XYZ);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync }
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync#endif
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync /*
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Load per-VM data.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync */
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync uint32_t uProviderId;
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync uint32_t uProviderVersion;
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync rc = SSMR3GetU32(pSSM, &uProviderId); AssertRCReturn(rc, rc);
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync rc = SSMR3GetU32(pSSM, &uProviderVersion); AssertRCReturn(rc, rc);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
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 uProviderId, pVM->gim.s.enmProviderId);
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync#if 0 /** @todo r=bird: Figure out what you mean to do here with the version. */
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync if (uProviderVersion != pVM->gim.s.u32Version)
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Saved GIM provider version %u differs from the configured one (%u)."),
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync uProviderVersion, pVM->gim.s.u32Version);
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync#else
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync pVM->gim.s.u32Version = uProviderVersion;
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync#endif
26f7a9a33aba00f6fe644eece95158d147ae3dbdvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync /*
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Load provider-specific data.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync */
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync switch (pVM->gim.s.enmProviderId)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync {
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync case GIMPROVIDERID_HYPERV:
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync rc = gimR3HvLoad(pVM, pSSM, uSSMVersion);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync AssertRCReturn(rc, rc);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync break;
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync case GIMPROVIDERID_KVM:
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync rc = gimR3KvmLoad(pVM, pSSM, uSSMVersion);
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync AssertRCReturn(rc, rc);
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync break;
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync default:
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync break;
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync }
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
4ae0ac3d0dc641305a0b0197db43ee7c4b40f747vboxsync return VINF_SUCCESS;
236b2935f217749893b7034e59da3e3568928acevboxsync}
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync
236b2935f217749893b7034e59da3e3568928acevboxsync/**
236b2935f217749893b7034e59da3e3568928acevboxsync * Terminates the GIM.
236b2935f217749893b7034e59da3e3568928acevboxsync *
236b2935f217749893b7034e59da3e3568928acevboxsync * Termination means cleaning up and freeing all resources,
236b2935f217749893b7034e59da3e3568928acevboxsync * the VM itself is, at this point, powered off or suspended.
236b2935f217749893b7034e59da3e3568928acevboxsync *
236b2935f217749893b7034e59da3e3568928acevboxsync * @returns VBox status code.
236b2935f217749893b7034e59da3e3568928acevboxsync * @param pVM Pointer to the VM.
236b2935f217749893b7034e59da3e3568928acevboxsync */
236b2935f217749893b7034e59da3e3568928acevboxsyncVMMR3_INT_DECL(int) GIMR3Term(PVM pVM)
236b2935f217749893b7034e59da3e3568928acevboxsync{
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync switch (pVM->gim.s.enmProviderId)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync {
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync case GIMPROVIDERID_HYPERV:
f84ab9e4599e758ec1f36479f871b3f5b7f271f2vboxsync return gimR3HvTerm(pVM);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync case GIMPROVIDERID_KVM:
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync return gimR3KvmTerm(pVM);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync default:
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync break;
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync }
236b2935f217749893b7034e59da3e3568928acevboxsync return VINF_SUCCESS;
236b2935f217749893b7034e59da3e3568928acevboxsync}
236b2935f217749893b7034e59da3e3568928acevboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync/**
157093a77f2752732368338110cb50fa6cd7717fvboxsync * The VM is being reset.
157093a77f2752732368338110cb50fa6cd7717fvboxsync *
157093a77f2752732368338110cb50fa6cd7717fvboxsync * For the GIM component this means unmapping and unregistering MMIO2 regions
157093a77f2752732368338110cb50fa6cd7717fvboxsync * and other provider-specific resets.
157093a77f2752732368338110cb50fa6cd7717fvboxsync *
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @returns VBox status code.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pVM Pointer to the VM.
157093a77f2752732368338110cb50fa6cd7717fvboxsync */
157093a77f2752732368338110cb50fa6cd7717fvboxsyncVMMR3_INT_DECL(void) GIMR3Reset(PVM pVM)
157093a77f2752732368338110cb50fa6cd7717fvboxsync{
157093a77f2752732368338110cb50fa6cd7717fvboxsync switch (pVM->gim.s.enmProviderId)
157093a77f2752732368338110cb50fa6cd7717fvboxsync {
157093a77f2752732368338110cb50fa6cd7717fvboxsync case GIMPROVIDERID_HYPERV:
f84ab9e4599e758ec1f36479f871b3f5b7f271f2vboxsync return gimR3HvReset(pVM);
157093a77f2752732368338110cb50fa6cd7717fvboxsync
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync case GIMPROVIDERID_KVM:
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync return gimR3KvmReset(pVM);
0bc35f54322c5f9b2d43b064f839a8cf8c99a234vboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync default:
157093a77f2752732368338110cb50fa6cd7717fvboxsync break;
157093a77f2752732368338110cb50fa6cd7717fvboxsync }
157093a77f2752732368338110cb50fa6cd7717fvboxsync}
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync/**
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Registers the GIM device with VMM.
157093a77f2752732368338110cb50fa6cd7717fvboxsync *
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pVM Pointer to the VM.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pDevIns Pointer to the GIM device instance.
157093a77f2752732368338110cb50fa6cd7717fvboxsync */
157093a77f2752732368338110cb50fa6cd7717fvboxsyncVMMR3DECL(void) GIMR3GimDeviceRegister(PVM pVM, PPDMDEVINS pDevIns)
157093a77f2752732368338110cb50fa6cd7717fvboxsync{
157093a77f2752732368338110cb50fa6cd7717fvboxsync pVM->gim.s.pDevInsR3 = pDevIns;
157093a77f2752732368338110cb50fa6cd7717fvboxsync}
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync/**
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 *
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 *
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @remarks The caller does not own and therefore must -NOT- try to free the
157093a77f2752732368338110cb50fa6cd7717fvboxsync * returned pointer.
157093a77f2752732368338110cb50fa6cd7717fvboxsync */
157093a77f2752732368338110cb50fa6cd7717fvboxsyncVMMR3DECL(PGIMMMIO2REGION) GIMR3GetMmio2Regions(PVM pVM, uint32_t *pcRegions)
157093a77f2752732368338110cb50fa6cd7717fvboxsync{
157093a77f2752732368338110cb50fa6cd7717fvboxsync Assert(pVM);
157093a77f2752732368338110cb50fa6cd7717fvboxsync Assert(pcRegions);
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync *pcRegions = 0;
157093a77f2752732368338110cb50fa6cd7717fvboxsync switch (pVM->gim.s.enmProviderId)
157093a77f2752732368338110cb50fa6cd7717fvboxsync {
157093a77f2752732368338110cb50fa6cd7717fvboxsync case GIMPROVIDERID_HYPERV:
f84ab9e4599e758ec1f36479f871b3f5b7f271f2vboxsync return gimR3HvGetMmio2Regions(pVM, pcRegions);
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync default:
157093a77f2752732368338110cb50fa6cd7717fvboxsync break;
157093a77f2752732368338110cb50fa6cd7717fvboxsync }
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync return NULL;
157093a77f2752732368338110cb50fa6cd7717fvboxsync}
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync/**
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Unmaps a registered MMIO2 region in the guest address space and removes any
157093a77f2752732368338110cb50fa6cd7717fvboxsync * access handlers for it.
157093a77f2752732368338110cb50fa6cd7717fvboxsync *
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @returns VBox status code.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pVM Pointer to the VM.
157093a77f2752732368338110cb50fa6cd7717fvboxsync * @param pRegion Pointer to the GIM MMIO2 region.
157093a77f2752732368338110cb50fa6cd7717fvboxsync */
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncVMMR3_INT_DECL(int) GIMR3Mmio2Unmap(PVM pVM, PGIMMMIO2REGION pRegion)
157093a77f2752732368338110cb50fa6cd7717fvboxsync{
157093a77f2752732368338110cb50fa6cd7717fvboxsync AssertPtr(pVM);
157093a77f2752732368338110cb50fa6cd7717fvboxsync AssertPtr(pRegion);
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync PPDMDEVINS pDevIns = pVM->gim.s.pDevInsR3;
157093a77f2752732368338110cb50fa6cd7717fvboxsync AssertPtr(pDevIns);
157093a77f2752732368338110cb50fa6cd7717fvboxsync if (pRegion->fMapped)
157093a77f2752732368338110cb50fa6cd7717fvboxsync {
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync int rc = PGMHandlerPhysicalDeregister(pVM, pRegion->GCPhysPage);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync AssertRC(rc);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync rc = PDMDevHlpMMIO2Unmap(pDevIns, pRegion->iRegion, pRegion->GCPhysPage);
157093a77f2752732368338110cb50fa6cd7717fvboxsync if (RT_SUCCESS(rc))
157093a77f2752732368338110cb50fa6cd7717fvboxsync {
157093a77f2752732368338110cb50fa6cd7717fvboxsync pRegion->fMapped = false;
157093a77f2752732368338110cb50fa6cd7717fvboxsync pRegion->GCPhysPage = NIL_RTGCPHYS;
157093a77f2752732368338110cb50fa6cd7717fvboxsync }
157093a77f2752732368338110cb50fa6cd7717fvboxsync }
157093a77f2752732368338110cb50fa6cd7717fvboxsync return VINF_SUCCESS;
157093a77f2752732368338110cb50fa6cd7717fvboxsync}
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync/**
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Write access handler for a mapped MMIO2 region. At present, this handler
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * simply ignores writes.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync *
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * In the future we might want to let the GIM provider decide what the handler
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * should do (like throwing #GP faults).
157093a77f2752732368338110cb50fa6cd7717fvboxsync *
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).
157093a77f2752732368338110cb50fa6cd7717fvboxsync */
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncstatic DECLCALLBACK(int) gimR3Mmio2WriteHandler(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync PGMACCESSTYPE enmAccessType, void *pvUser)
157093a77f2752732368338110cb50fa6cd7717fvboxsync{
157093a77f2752732368338110cb50fa6cd7717fvboxsync /*
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Ignore writes to the mapped MMIO2 page.
157093a77f2752732368338110cb50fa6cd7717fvboxsync */
157093a77f2752732368338110cb50fa6cd7717fvboxsync Assert(enmAccessType == PGMACCESSTYPE_WRITE);
157093a77f2752732368338110cb50fa6cd7717fvboxsync return VINF_SUCCESS; /** @todo Hyper-V says we should #GP(0) fault for writes to the Hypercall and TSC page. */
157093a77f2752732368338110cb50fa6cd7717fvboxsync}
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync/**
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 *
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.
157093a77f2752732368338110cb50fa6cd7717fvboxsync */
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncVMMR3_INT_DECL(int) GIMR3Mmio2Map(PVM pVM, PGIMMMIO2REGION pRegion, RTGCPHYS GCPhysRegion)
157093a77f2752732368338110cb50fa6cd7717fvboxsync{
157093a77f2752732368338110cb50fa6cd7717fvboxsync PPDMDEVINS pDevIns = pVM->gim.s.pDevInsR3;
157093a77f2752732368338110cb50fa6cd7717fvboxsync AssertPtr(pDevIns);
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync /* The guest-physical address must be page-aligned. */
157093a77f2752732368338110cb50fa6cd7717fvboxsync if (GCPhysRegion & PAGE_OFFSET_MASK)
157093a77f2752732368338110cb50fa6cd7717fvboxsync {
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync LogFunc(("%s: %#RGp not paging aligned\n", pRegion->szDescription, GCPhysRegion));
157093a77f2752732368338110cb50fa6cd7717fvboxsync return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
157093a77f2752732368338110cb50fa6cd7717fvboxsync }
157093a77f2752732368338110cb50fa6cd7717fvboxsync
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. */
157093a77f2752732368338110cb50fa6cd7717fvboxsync if (!PGMPhysIsGCPhysNormal(pVM, GCPhysRegion))
157093a77f2752732368338110cb50fa6cd7717fvboxsync {
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync LogFunc(("%s: %#RGp is not normal memory\n", pRegion->szDescription, GCPhysRegion));
157093a77f2752732368338110cb50fa6cd7717fvboxsync return VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS;
157093a77f2752732368338110cb50fa6cd7717fvboxsync }
157093a77f2752732368338110cb50fa6cd7717fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync if (!pRegion->fRegistered)
157093a77f2752732368338110cb50fa6cd7717fvboxsync {
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync LogFunc(("%s: Region has not been registered.\n"));
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync return VERR_GIM_IPE_1;
157093a77f2752732368338110cb50fa6cd7717fvboxsync }
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync /*
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Map the MMIO2 region over the specified guest-physical address.
157093a77f2752732368338110cb50fa6cd7717fvboxsync */
157093a77f2752732368338110cb50fa6cd7717fvboxsync int rc = PDMDevHlpMMIO2Map(pDevIns, pRegion->iRegion, GCPhysRegion);
157093a77f2752732368338110cb50fa6cd7717fvboxsync if (RT_SUCCESS(rc))
157093a77f2752732368338110cb50fa6cd7717fvboxsync {
157093a77f2752732368338110cb50fa6cd7717fvboxsync /*
157093a77f2752732368338110cb50fa6cd7717fvboxsync * Install access-handlers for the mapped page to prevent (ignore) writes to it from the guest.
157093a77f2752732368338110cb50fa6cd7717fvboxsync */
157093a77f2752732368338110cb50fa6cd7717fvboxsync rc = PGMR3HandlerPhysicalRegister(pVM,
157093a77f2752732368338110cb50fa6cd7717fvboxsync PGMPHYSHANDLERTYPE_PHYSICAL_WRITE,
157093a77f2752732368338110cb50fa6cd7717fvboxsync GCPhysRegion, GCPhysRegion + (pRegion->cbRegion - 1),
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync gimR3Mmio2WriteHandler, NULL /* pvUserR3 */,
157093a77f2752732368338110cb50fa6cd7717fvboxsync NULL /* pszModR0 */, NULL /* pszHandlerR0 */, NIL_RTR0PTR /* pvUserR0 */,
157093a77f2752732368338110cb50fa6cd7717fvboxsync NULL /* pszModRC */, NULL /* pszHandlerRC */, NIL_RTRCPTR /* pvUserRC */,
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync pRegion->szDescription);
157093a77f2752732368338110cb50fa6cd7717fvboxsync if (RT_SUCCESS(rc))
157093a77f2752732368338110cb50fa6cd7717fvboxsync {
157093a77f2752732368338110cb50fa6cd7717fvboxsync pRegion->fMapped = true;
157093a77f2752732368338110cb50fa6cd7717fvboxsync pRegion->GCPhysPage = GCPhysRegion;
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync return rc;
157093a77f2752732368338110cb50fa6cd7717fvboxsync }
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync PDMDevHlpMMIO2Unmap(pDevIns, pRegion->iRegion, GCPhysRegion);
157093a77f2752732368338110cb50fa6cd7717fvboxsync }
157093a77f2752732368338110cb50fa6cd7717fvboxsync
157093a77f2752732368338110cb50fa6cd7717fvboxsync return rc;
157093a77f2752732368338110cb50fa6cd7717fvboxsync}
157093a77f2752732368338110cb50fa6cd7717fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync#if 0
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync/**
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Registers the physical handler for the registered and mapped MMIO2 region.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync *
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @returns VBox status code.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pVM Pointer to the VM.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pRegion Pointer to the GIM MMIO2 region.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync */
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncVMMR3_INT_DECL(int) GIMR3Mmio2HandlerPhysicalRegister(PVM pVM, PGIMMMIO2REGION pRegion)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync{
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync AssertPtr(pRegion);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync AssertReturn(pRegion->fRegistered, VERR_GIM_IPE_2);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync AssertReturn(pRegion->fMapped, VERR_GIM_IPE_3);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync return PGMR3HandlerPhysicalRegister(pVM,
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync PGMPHYSHANDLERTYPE_PHYSICAL_WRITE,
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync pRegion->GCPhysPage, pRegion->GCPhysPage + (pRegion->cbRegion - 1),
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync gimR3Mmio2WriteHandler, NULL /* pvUserR3 */,
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync NULL /* pszModR0 */, NULL /* pszHandlerR0 */, NIL_RTR0PTR /* pvUserR0 */,
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync NULL /* pszModRC */, NULL /* pszHandlerRC */, NIL_RTRCPTR /* pvUserRC */,
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync pRegion->szDescription);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync}
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync/**
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * Deregisters the physical handler for the MMIO2 region.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync *
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @returns VBox status code.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pVM Pointer to the VM.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync * @param pRegion Pointer to the GIM MMIO2 region.
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync */
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsyncVMMR3_INT_DECL(int) GIMR3Mmio2HandlerPhysicalDeregister(PVM pVM, PGIMMMIO2REGION pRegion)
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync{
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync return PGMHandlerPhysicalDeregister(pVM, pRegion->GCPhysPage);
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync}
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync#endif
2ac3892cdc8b16a0dee55e8b4510b8ecea83c95fvboxsync