summaryrefslogtreecommitdiff
path: root/include/VBox/vmm
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@baserock.org>2012-10-26 16:25:44 +0000
committer <>2012-11-12 12:15:52 +0000
commit58ed4748338f9466599adfc8a9171280ed99e23f (patch)
tree02027d99ded4fb56a64aa9489ac2eb487e7858ab /include/VBox/vmm
downloadVirtualBox-58ed4748338f9466599adfc8a9171280ed99e23f.tar.gz
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.2.4.tar.bz2.VirtualBox-4.2.4
Diffstat (limited to 'include/VBox/vmm')
-rw-r--r--include/VBox/vmm/Makefile.kup0
-rw-r--r--include/VBox/vmm/cfgm.h220
-rw-r--r--include/VBox/vmm/cpum.h492
-rw-r--r--include/VBox/vmm/cpum.mac207
-rw-r--r--include/VBox/vmm/cpumctx-v1_6.h249
-rw-r--r--include/VBox/vmm/cpumctx.h477
-rw-r--r--include/VBox/vmm/cpumdis.h48
-rw-r--r--include/VBox/vmm/csam.h305
-rw-r--r--include/VBox/vmm/dbgf.h1658
-rw-r--r--include/VBox/vmm/dbgfcorefmt.h79
-rw-r--r--include/VBox/vmm/dbgfsel.h104
-rw-r--r--include/VBox/vmm/dbgftrace.h143
-rw-r--r--include/VBox/vmm/em.h276
-rw-r--r--include/VBox/vmm/ftm.h71
-rw-r--r--include/VBox/vmm/gmm.h809
-rw-r--r--include/VBox/vmm/gvm.h124
-rw-r--r--include/VBox/vmm/gvmm.h268
-rw-r--r--include/VBox/vmm/hwacc_svm.h744
-rw-r--r--include/VBox/vmm/hwacc_vmx.h1708
-rw-r--r--include/VBox/vmm/hwacc_vmx.mac154
-rw-r--r--include/VBox/vmm/hwaccm.h154
-rw-r--r--include/VBox/vmm/iem.h83
-rw-r--r--include/VBox/vmm/iom.h325
-rw-r--r--include/VBox/vmm/mm.h370
-rw-r--r--include/VBox/vmm/patm.h672
-rw-r--r--include/VBox/vmm/pdm.h40
-rw-r--r--include/VBox/vmm/pdmapi.h210
-rw-r--r--include/VBox/vmm/pdmasynccompletion.h368
-rw-r--r--include/VBox/vmm/pdmasynctask.h61
-rw-r--r--include/VBox/vmm/pdmblkcache.h422
-rw-r--r--include/VBox/vmm/pdmcardreaderinfs.h116
-rw-r--r--include/VBox/vmm/pdmcommon.h164
-rw-r--r--include/VBox/vmm/pdmcritsect.h95
-rw-r--r--include/VBox/vmm/pdmdev.h5173
-rw-r--r--include/VBox/vmm/pdmdrv.h1829
-rw-r--r--include/VBox/vmm/pdmifs.h2996
-rw-r--r--include/VBox/vmm/pdmins.h70
-rw-r--r--include/VBox/vmm/pdmnetifs.h437
-rw-r--r--include/VBox/vmm/pdmnetinline.h664
-rw-r--r--include/VBox/vmm/pdmnetshaper.h120
-rw-r--r--include/VBox/vmm/pdmnetshaperint.h94
-rw-r--r--include/VBox/vmm/pdmnvram.h70
-rw-r--r--include/VBox/vmm/pdmpci.h398
-rw-r--r--include/VBox/vmm/pdmqueue.h147
-rw-r--r--include/VBox/vmm/pdmsrv.h335
-rw-r--r--include/VBox/vmm/pdmthread.h298
-rw-r--r--include/VBox/vmm/pdmusb.h1004
-rw-r--r--include/VBox/vmm/pgm.h586
-rw-r--r--include/VBox/vmm/rem.h106
-rw-r--r--include/VBox/vmm/selm.h123
-rw-r--r--include/VBox/vmm/ssm.h1265
-rw-r--r--include/VBox/vmm/stam.h1265
-rw-r--r--include/VBox/vmm/stam.mac382
-rw-r--r--include/VBox/vmm/tm.h281
-rw-r--r--include/VBox/vmm/trpm.h150
-rw-r--r--include/VBox/vmm/trpm.mac47
-rw-r--r--include/VBox/vmm/uvm.h152
-rw-r--r--include/VBox/vmm/vm.h1106
-rw-r--r--include/VBox/vmm/vm.mac150
-rw-r--r--include/VBox/vmm/vmapi.h441
-rw-r--r--include/VBox/vmm/vmcpuset.h107
-rw-r--r--include/VBox/vmm/vmm.h522
62 files changed, 31534 insertions, 0 deletions
diff --git a/include/VBox/vmm/Makefile.kup b/include/VBox/vmm/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/include/VBox/vmm/Makefile.kup
diff --git a/include/VBox/vmm/cfgm.h b/include/VBox/vmm/cfgm.h
new file mode 100644
index 00000000..9b4e47ab
--- /dev/null
+++ b/include/VBox/vmm/cfgm.h
@@ -0,0 +1,220 @@
+/** @file
+ * CFGM - Configuration Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_cfgm_h
+#define ___VBox_vmm_cfgm_h
+
+#include <VBox/types.h>
+#include <iprt/stdarg.h>
+
+/** @defgroup grp_cfgm The Configuration Manager API
+ * @{
+ */
+
+/**
+ * Configuration manager value type.
+ */
+typedef enum CFGMVALUETYPE
+{
+ /** Integer value. */
+ CFGMVALUETYPE_INTEGER = 1,
+ /** String value. */
+ CFGMVALUETYPE_STRING,
+ /** Bytestring value. */
+ CFGMVALUETYPE_BYTES
+} CFGMVALUETYPE;
+/** Pointer to configuration manager property type. */
+typedef CFGMVALUETYPE *PCFGMVALUETYPE;
+
+
+
+RT_C_DECLS_BEGIN
+
+#ifdef IN_RING3
+/** @defgroup grp_cfgm_r3 The CFGM Host Context Ring-3 API
+ * @ingroup grp_cfgm
+ * @{
+ */
+
+typedef enum CFGMCONFIGTYPE
+{
+ /** pvConfig points to nothing, use defaults. */
+ CFGMCONFIGTYPE_NONE = 0,
+ /** pvConfig points to a IMachine interface. */
+ CFGMCONFIGTYPE_IMACHINE
+} CFGMCONFIGTYPE;
+
+
+/**
+ * CFGM init callback for constructing the configuration tree.
+ *
+ * This is called from the emulation thread, and the one interfacing the VM
+ * can make any necessary per-thread initializations at this point.
+ *
+ * @returns VBox status code.
+ * @param pVM VM handle.
+ * @param pvUser The argument supplied to VMR3Create().
+ */
+typedef DECLCALLBACK(int) FNCFGMCONSTRUCTOR(PVM pVM, void *pvUser);
+/** Pointer to a FNCFGMCONSTRUCTOR(). */
+typedef FNCFGMCONSTRUCTOR *PFNCFGMCONSTRUCTOR;
+
+VMMR3DECL(int) CFGMR3Init(PVM pVM, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUser);
+VMMR3DECL(int) CFGMR3Term(PVM pVM);
+
+
+VMMR3DECL(PCFGMNODE) CFGMR3CreateTree(PVM pVM);
+VMMR3DECL(int) CFGMR3ConstructDefaultTree(PVM pVM);
+VMMR3DECL(void) CFGMR3Dump(PCFGMNODE pRoot);
+VMMR3DECL(int) CFGMR3DuplicateSubTree(PCFGMNODE pRoot, PCFGMNODE *ppCopy);
+VMMR3DECL(int) CFGMR3ReplaceSubTree(PCFGMNODE pRoot, PCFGMNODE pNewRoot);
+VMMR3DECL(int) CFGMR3InsertSubTree(PCFGMNODE pNode, const char *pszName, PCFGMNODE pSubTree, PCFGMNODE *ppChild);
+VMMR3DECL(int) CFGMR3InsertNode(PCFGMNODE pNode, const char *pszName, PCFGMNODE *ppChild);
+VMMR3DECL(int) CFGMR3InsertNodeF(PCFGMNODE pNode, PCFGMNODE *ppChild, const char *pszNameFormat, ...);
+VMMR3DECL(int) CFGMR3InsertNodeFV(PCFGMNODE pNode, PCFGMNODE *ppChild, const char *pszNameFormat, va_list Args);
+VMMR3DECL(void) CFGMR3SetRestrictedRoot(PCFGMNODE pNode);
+VMMR3DECL(void) CFGMR3RemoveNode(PCFGMNODE pNode);
+VMMR3DECL(int) CFGMR3InsertInteger(PCFGMNODE pNode, const char *pszName, uint64_t u64Integer);
+VMMR3DECL(int) CFGMR3InsertString(PCFGMNODE pNode, const char *pszName, const char *pszString);
+VMMR3DECL(int) CFGMR3InsertStringN(PCFGMNODE pNode, const char *pszName, const char *pszString, size_t cchString);
+VMMR3DECL(int) CFGMR3InsertStringF(PCFGMNODE pNode, const char *pszName, const char *pszFormat, ...);
+VMMR3DECL(int) CFGMR3InsertStringFV(PCFGMNODE pNode, const char *pszName, const char *pszFormat, va_list va);
+VMMR3DECL(int) CFGMR3InsertStringW(PCFGMNODE pNode, const char *pszName, PCRTUTF16 pwszValue);
+VMMR3DECL(int) CFGMR3InsertBytes(PCFGMNODE pNode, const char *pszName, const void *pvBytes, size_t cbBytes);
+VMMR3DECL(int) CFGMR3InsertValue(PCFGMNODE pNode, PCFGMLEAF pValue);
+VMMR3DECL(int) CFGMR3RemoveValue(PCFGMNODE pNode, const char *pszName);
+
+/** @name CFGMR3CopyTree flags.
+ * @{ */
+/** Reserved value disposition \#0. */
+#define CFGM_COPY_FLAGS_RESERVED_VALUE_DISP_0 UINT32_C(0x00000000)
+/** Reserved value disposition \#1. */
+#define CFGM_COPY_FLAGS_RESERVED_VALUE_DISP_1 UINT32_C(0x00000001)
+/** Replace exiting values. */
+#define CFGM_COPY_FLAGS_REPLACE_VALUES UINT32_C(0x00000002)
+/** Ignore exiting values. */
+#define CFGM_COPY_FLAGS_IGNORE_EXISTING_VALUES UINT32_C(0x00000003)
+/** Value disposition mask. */
+#define CFGM_COPY_FLAGS_VALUE_DISP_MASK UINT32_C(0x00000003)
+
+/** Replace exiting keys. */
+#define CFGM_COPY_FLAGS_RESERVED_KEY_DISP UINT32_C(0x00000000)
+/** Replace exiting keys. */
+#define CFGM_COPY_FLAGS_MERGE_KEYS UINT32_C(0x00000010)
+/** Replace exiting keys. */
+#define CFGM_COPY_FLAGS_REPLACE_KEYS UINT32_C(0x00000020)
+/** Ignore existing keys. */
+#define CFGM_COPY_FLAGS_IGNORE_EXISTING_KEYS UINT32_C(0x00000030)
+/** Key disposition. */
+#define CFGM_COPY_FLAGS_KEY_DISP_MASK UINT32_C(0x00000030)
+/** @} */
+VMMR3DECL(int) CFGMR3CopyTree(PCFGMNODE pDstTree, PCFGMNODE pSrcTree, uint32_t fFlags);
+
+VMMR3DECL(int) CFGMR3QueryType( PCFGMNODE pNode, const char *pszName, PCFGMVALUETYPE penmType);
+VMMR3DECL(int) CFGMR3QuerySize( PCFGMNODE pNode, const char *pszName, size_t *pcb);
+VMMR3DECL(int) CFGMR3QueryInteger( PCFGMNODE pNode, const char *pszName, uint64_t *pu64);
+VMMR3DECL(int) CFGMR3QueryIntegerDef( PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def);
+VMMR3DECL(int) CFGMR3QueryString( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString);
+VMMR3DECL(int) CFGMR3QueryStringDef( PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString, const char *pszDef);
+VMMR3DECL(int) CFGMR3QueryBytes( PCFGMNODE pNode, const char *pszName, void *pvData, size_t cbData);
+
+
+/** @name Helpers
+ * @{
+ */
+VMMR3DECL(int) CFGMR3QueryU64( PCFGMNODE pNode, const char *pszName, uint64_t *pu64);
+VMMR3DECL(int) CFGMR3QueryU64Def( PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def);
+VMMR3DECL(int) CFGMR3QueryS64( PCFGMNODE pNode, const char *pszName, int64_t *pi64);
+VMMR3DECL(int) CFGMR3QueryS64Def( PCFGMNODE pNode, const char *pszName, int64_t *pi64, int64_t i64Def);
+VMMR3DECL(int) CFGMR3QueryU32( PCFGMNODE pNode, const char *pszName, uint32_t *pu32);
+VMMR3DECL(int) CFGMR3QueryU32Def( PCFGMNODE pNode, const char *pszName, uint32_t *pu32, uint32_t u32Def);
+VMMR3DECL(int) CFGMR3QueryS32( PCFGMNODE pNode, const char *pszName, int32_t *pi32);
+VMMR3DECL(int) CFGMR3QueryS32Def( PCFGMNODE pNode, const char *pszName, int32_t *pi32, int32_t i32Def);
+VMMR3DECL(int) CFGMR3QueryU16( PCFGMNODE pNode, const char *pszName, uint16_t *pu16);
+VMMR3DECL(int) CFGMR3QueryU16Def( PCFGMNODE pNode, const char *pszName, uint16_t *pu16, uint16_t u16Def);
+VMMR3DECL(int) CFGMR3QueryS16( PCFGMNODE pNode, const char *pszName, int16_t *pi16);
+VMMR3DECL(int) CFGMR3QueryS16Def( PCFGMNODE pNode, const char *pszName, int16_t *pi16, int16_t i16Def);
+VMMR3DECL(int) CFGMR3QueryU8( PCFGMNODE pNode, const char *pszName, uint8_t *pu8);
+VMMR3DECL(int) CFGMR3QueryU8Def( PCFGMNODE pNode, const char *pszName, uint8_t *pu8, uint8_t u8Def);
+VMMR3DECL(int) CFGMR3QueryS8( PCFGMNODE pNode, const char *pszName, int8_t *pi8);
+VMMR3DECL(int) CFGMR3QueryS8Def( PCFGMNODE pNode, const char *pszName, int8_t *pi8, int8_t i8Def);
+VMMR3DECL(int) CFGMR3QueryBool( PCFGMNODE pNode, const char *pszName, bool *pf);
+VMMR3DECL(int) CFGMR3QueryBoolDef( PCFGMNODE pNode, const char *pszName, bool *pf, bool fDef);
+VMMR3DECL(int) CFGMR3QueryPort( PCFGMNODE pNode, const char *pszName, PRTIOPORT pPort);
+VMMR3DECL(int) CFGMR3QueryPortDef( PCFGMNODE pNode, const char *pszName, PRTIOPORT pPort, RTIOPORT PortDef);
+VMMR3DECL(int) CFGMR3QueryUInt( PCFGMNODE pNode, const char *pszName, unsigned int *pu);
+VMMR3DECL(int) CFGMR3QueryUIntDef( PCFGMNODE pNode, const char *pszName, unsigned int *pu, unsigned int uDef);
+VMMR3DECL(int) CFGMR3QuerySInt( PCFGMNODE pNode, const char *pszName, signed int *pi);
+VMMR3DECL(int) CFGMR3QuerySIntDef( PCFGMNODE pNode, const char *pszName, signed int *pi, signed int iDef);
+VMMR3DECL(int) CFGMR3QueryPtr( PCFGMNODE pNode, const char *pszName, void **ppv);
+VMMR3DECL(int) CFGMR3QueryPtrDef( PCFGMNODE pNode, const char *pszName, void **ppv, void *pvDef);
+VMMR3DECL(int) CFGMR3QueryGCPtr( PCFGMNODE pNode, const char *pszName, PRTGCPTR pGCPtr);
+VMMR3DECL(int) CFGMR3QueryGCPtrDef( PCFGMNODE pNode, const char *pszName, PRTGCPTR pGCPtr, RTGCPTR GCPtrDef);
+VMMR3DECL(int) CFGMR3QueryGCPtrU( PCFGMNODE pNode, const char *pszName, PRTGCUINTPTR pGCPtr);
+VMMR3DECL(int) CFGMR3QueryGCPtrUDef( PCFGMNODE pNode, const char *pszName, PRTGCUINTPTR pGCPtr, RTGCUINTPTR GCPtrDef);
+VMMR3DECL(int) CFGMR3QueryGCPtrS( PCFGMNODE pNode, const char *pszName, PRTGCINTPTR pGCPtr);
+VMMR3DECL(int) CFGMR3QueryGCPtrSDef( PCFGMNODE pNode, const char *pszName, PRTGCINTPTR pGCPtr, RTGCINTPTR GCPtrDef);
+VMMR3DECL(int) CFGMR3QueryStringAlloc( PCFGMNODE pNode, const char *pszName, char **ppszString);
+VMMR3DECL(int) CFGMR3QueryStringAllocDef(PCFGMNODE pNode, const char *pszName, char **ppszString, const char *pszDef);
+
+/** @} */
+
+/** @name Tree Navigation and Enumeration.
+ * @{
+ */
+VMMR3DECL(PCFGMNODE) CFGMR3GetRoot(PVM pVM);
+VMMR3DECL(PCFGMNODE) CFGMR3GetParent(PCFGMNODE pNode);
+VMMR3DECL(PCFGMNODE) CFGMR3GetParentEx(PVM pVM, PCFGMNODE pNode);
+VMMR3DECL(PCFGMNODE) CFGMR3GetChild(PCFGMNODE pNode, const char *pszPath);
+VMMR3DECL(PCFGMNODE) CFGMR3GetChildF(PCFGMNODE pNode, const char *pszPathFormat, ...);
+VMMR3DECL(PCFGMNODE) CFGMR3GetChildFV(PCFGMNODE pNode, const char *pszPathFormat, va_list Args);
+VMMR3DECL(PCFGMNODE) CFGMR3GetFirstChild(PCFGMNODE pNode);
+VMMR3DECL(PCFGMNODE) CFGMR3GetNextChild(PCFGMNODE pCur);
+VMMR3DECL(int) CFGMR3GetName(PCFGMNODE pCur, char *pszName, size_t cchName);
+VMMR3DECL(size_t) CFGMR3GetNameLen(PCFGMNODE pCur);
+VMMR3DECL(bool) CFGMR3AreChildrenValid(PCFGMNODE pNode, const char *pszzValid);
+VMMR3DECL(PCFGMLEAF) CFGMR3GetFirstValue(PCFGMNODE pCur);
+VMMR3DECL(PCFGMLEAF) CFGMR3GetNextValue(PCFGMLEAF pCur);
+VMMR3DECL(int) CFGMR3GetValueName(PCFGMLEAF pCur, char *pszName, size_t cchName);
+VMMR3DECL(size_t) CFGMR3GetValueNameLen(PCFGMLEAF pCur);
+VMMR3DECL(CFGMVALUETYPE) CFGMR3GetValueType(PCFGMLEAF pCur);
+VMMR3DECL(bool) CFGMR3AreValuesValid(PCFGMNODE pNode, const char *pszzValid);
+VMMR3DECL(int) CFGMR3ValidateConfig(PCFGMNODE pNode, const char *pszNode,
+ const char *pszValidValues, const char *pszValidNodes,
+ const char *pszWho, uint32_t uInstance);
+
+/** @} */
+
+
+/** @} */
+#endif /* IN_RING3 */
+
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif
+
diff --git a/include/VBox/vmm/cpum.h b/include/VBox/vmm/cpum.h
new file mode 100644
index 00000000..0b4abf33
--- /dev/null
+++ b/include/VBox/vmm/cpum.h
@@ -0,0 +1,492 @@
+/** @file
+ * CPUM - CPU Monitor(/ Manager).
+ */
+
+/*
+ * Copyright (C) 2006-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_cpum_h
+#define ___VBox_vmm_cpum_h
+
+#include <iprt/x86.h>
+#include <VBox/types.h>
+#include <VBox/vmm/cpumctx.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_cpum The CPU Monitor / Manager API
+ * @{
+ */
+
+/**
+ * CPUID feature to set or clear.
+ */
+typedef enum CPUMCPUIDFEATURE
+{
+ CPUMCPUIDFEATURE_INVALID = 0,
+ /** The APIC feature bit. (Std+Ext) */
+ CPUMCPUIDFEATURE_APIC,
+ /** The sysenter/sysexit feature bit. (Std) */
+ CPUMCPUIDFEATURE_SEP,
+ /** The SYSCALL/SYSEXIT feature bit (64 bits mode only for Intel CPUs). (Ext) */
+ CPUMCPUIDFEATURE_SYSCALL,
+ /** The PAE feature bit. (Std+Ext) */
+ CPUMCPUIDFEATURE_PAE,
+ /** The NX feature bit. (Ext) */
+ CPUMCPUIDFEATURE_NX,
+ /** The LAHF/SAHF feature bit (64 bits mode only). (Ext) */
+ CPUMCPUIDFEATURE_LAHF,
+ /** The LONG MODE feature bit. (Ext) */
+ CPUMCPUIDFEATURE_LONG_MODE,
+ /** The PAT feature bit. (Std+Ext) */
+ CPUMCPUIDFEATURE_PAT,
+ /** The x2APIC feature bit. (Std) */
+ CPUMCPUIDFEATURE_X2APIC,
+ /** The RDTSCP feature bit. (Ext) */
+ CPUMCPUIDFEATURE_RDTSCP,
+ /** The Hypervisor Present bit. (Std) */
+ CPUMCPUIDFEATURE_HVP,
+ /** 32bit hackishness. */
+ CPUMCPUIDFEATURE_32BIT_HACK = 0x7fffffff
+} CPUMCPUIDFEATURE;
+
+/**
+ * CPU Vendor.
+ */
+typedef enum CPUMCPUVENDOR
+{
+ CPUMCPUVENDOR_INVALID = 0,
+ CPUMCPUVENDOR_INTEL,
+ CPUMCPUVENDOR_AMD,
+ CPUMCPUVENDOR_VIA,
+ CPUMCPUVENDOR_UNKNOWN,
+ CPUMCPUVENDOR_SYNTHETIC,
+ /** 32bit hackishness. */
+ CPUMCPUVENDOR_32BIT_HACK = 0x7fffffff
+} CPUMCPUVENDOR;
+
+
+/** @name Guest Register Getters.
+ * @{ */
+VMMDECL(void) CPUMGetGuestGDTR(PVMCPU pVCpu, PVBOXGDTR pGDTR);
+VMMDECL(RTGCPTR) CPUMGetGuestIDTR(PVMCPU pVCpu, uint16_t *pcbLimit);
+VMMDECL(RTSEL) CPUMGetGuestTR(PVMCPU pVCpu, PCPUMSELREGHID pHidden);
+VMMDECL(RTSEL) CPUMGetGuestLDTR(PVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetGuestLdtrEx(PVMCPU pVCpu, uint64_t *pGCPtrBase, uint32_t *pcbLimit);
+VMMDECL(uint64_t) CPUMGetGuestCR0(PVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestCR2(PVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestCR3(PVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestCR4(PVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestCR8(PVMCPU pVCpu);
+VMMDECL(int) CPUMGetGuestCRx(PVMCPU pVCpu, unsigned iReg, uint64_t *pValue);
+VMMDECL(uint32_t) CPUMGetGuestEFlags(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestEIP(PVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestRIP(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestEAX(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestEBX(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestECX(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestEDX(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestESI(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestEDI(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestESP(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestEBP(PVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetGuestCS(PVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetGuestDS(PVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetGuestES(PVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetGuestFS(PVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetGuestGS(PVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetGuestSS(PVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestDR0(PVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestDR1(PVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestDR2(PVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestDR3(PVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestDR6(PVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetGuestDR7(PVMCPU pVCpu);
+VMMDECL(int) CPUMGetGuestDRx(PVMCPU pVCpu, uint32_t iReg, uint64_t *pValue);
+VMMDECL(void) CPUMGetGuestCpuId(PVMCPU pVCpu, uint32_t iLeaf, uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx);
+VMMDECL(uint32_t) CPUMGetGuestCpuIdStdMax(PVM pVM);
+VMMDECL(uint32_t) CPUMGetGuestCpuIdExtMax(PVM pVM);
+VMMDECL(uint32_t) CPUMGetGuestCpuIdCentaurMax(PVM pVM);
+VMMDECL(uint64_t) CPUMGetGuestEFER(PVMCPU pVCpu);
+VMMDECL(int) CPUMQueryGuestMsr(PVMCPU pVCpu, uint32_t idMsr, uint64_t *puValue);
+VMMDECL(int) CPUMSetGuestMsr(PVMCPU pVCpu, uint32_t idMsr, uint64_t uValue);
+VMMDECL(CPUMCPUVENDOR) CPUMGetGuestCpuVendor(PVM pVM);
+VMMDECL(CPUMCPUVENDOR) CPUMGetHostCpuVendor(PVM pVM);
+/** @} */
+
+/** @name Guest Register Setters.
+ * @{ */
+VMMDECL(int) CPUMSetGuestGDTR(PVMCPU pVCpu, uint64_t GCPtrBase, uint16_t cbLimit);
+VMMDECL(int) CPUMSetGuestIDTR(PVMCPU pVCpu, uint64_t GCPtrBase, uint16_t cbLimit);
+VMMDECL(int) CPUMSetGuestTR(PVMCPU pVCpu, uint16_t tr);
+VMMDECL(int) CPUMSetGuestLDTR(PVMCPU pVCpu, uint16_t ldtr);
+VMMDECL(int) CPUMSetGuestCR0(PVMCPU pVCpu, uint64_t cr0);
+VMMDECL(int) CPUMSetGuestCR2(PVMCPU pVCpu, uint64_t cr2);
+VMMDECL(int) CPUMSetGuestCR3(PVMCPU pVCpu, uint64_t cr3);
+VMMDECL(int) CPUMSetGuestCR4(PVMCPU pVCpu, uint64_t cr4);
+VMMDECL(int) CPUMSetGuestDR0(PVMCPU pVCpu, uint64_t uDr0);
+VMMDECL(int) CPUMSetGuestDR1(PVMCPU pVCpu, uint64_t uDr1);
+VMMDECL(int) CPUMSetGuestDR2(PVMCPU pVCpu, uint64_t uDr2);
+VMMDECL(int) CPUMSetGuestDR3(PVMCPU pVCpu, uint64_t uDr3);
+VMMDECL(int) CPUMSetGuestDR6(PVMCPU pVCpu, uint64_t uDr6);
+VMMDECL(int) CPUMSetGuestDR7(PVMCPU pVCpu, uint64_t uDr7);
+VMMDECL(int) CPUMSetGuestDRx(PVMCPU pVCpu, uint32_t iReg, uint64_t Value);
+VMMDECL(int) CPUMSetGuestEFlags(PVMCPU pVCpu, uint32_t eflags);
+VMMDECL(int) CPUMSetGuestEIP(PVMCPU pVCpu, uint32_t eip);
+VMMDECL(int) CPUMSetGuestEAX(PVMCPU pVCpu, uint32_t eax);
+VMMDECL(int) CPUMSetGuestEBX(PVMCPU pVCpu, uint32_t ebx);
+VMMDECL(int) CPUMSetGuestECX(PVMCPU pVCpu, uint32_t ecx);
+VMMDECL(int) CPUMSetGuestEDX(PVMCPU pVCpu, uint32_t edx);
+VMMDECL(int) CPUMSetGuestESI(PVMCPU pVCpu, uint32_t esi);
+VMMDECL(int) CPUMSetGuestEDI(PVMCPU pVCpu, uint32_t edi);
+VMMDECL(int) CPUMSetGuestESP(PVMCPU pVCpu, uint32_t esp);
+VMMDECL(int) CPUMSetGuestEBP(PVMCPU pVCpu, uint32_t ebp);
+VMMDECL(int) CPUMSetGuestCS(PVMCPU pVCpu, uint16_t cs);
+VMMDECL(int) CPUMSetGuestDS(PVMCPU pVCpu, uint16_t ds);
+VMMDECL(int) CPUMSetGuestES(PVMCPU pVCpu, uint16_t es);
+VMMDECL(int) CPUMSetGuestFS(PVMCPU pVCpu, uint16_t fs);
+VMMDECL(int) CPUMSetGuestGS(PVMCPU pVCpu, uint16_t gs);
+VMMDECL(int) CPUMSetGuestSS(PVMCPU pVCpu, uint16_t ss);
+VMMDECL(void) CPUMSetGuestEFER(PVMCPU pVCpu, uint64_t val);
+VMMDECL(void) CPUMSetGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeature);
+VMMDECL(void) CPUMClearGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeature);
+VMMDECL(bool) CPUMGetGuestCpuIdFeature(PVM pVM, CPUMCPUIDFEATURE enmFeature);
+VMMDECL(void) CPUMSetGuestCtx(PVMCPU pVCpu, const PCPUMCTX pCtx);
+VMM_INT_DECL(void) CPUMGuestLazyLoadHiddenCsAndSs(PVMCPU pVCpu);
+VMM_INT_DECL(void) CPUMGuestLazyLoadHiddenSelectorReg(PVMCPU pVCpu, PCPUMSELREG pSReg);
+/** @} */
+
+
+/** @name Misc Guest Predicate Functions.
+ * @{ */
+
+VMMDECL(bool) CPUMIsGuestIn16BitCode(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestIn32BitCode(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestIn64BitCode(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestNXEnabled(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestPageSizeExtEnabled(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestPagingEnabled(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestR0WriteProtEnabled(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestInRealMode(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestInRealOrV86Mode(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestInProtectedMode(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestInPagedProtectedMode(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestInLongMode(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestInPAEMode(PVMCPU pVCpu);
+VMM_INT_DECL(bool) CPUMIsGuestInRawMode(PVMCPU pVCpu);
+
+#ifndef VBOX_WITHOUT_UNNAMED_UNIONS
+
+/**
+ * Tests if the guest is running in real mode or not.
+ *
+ * @returns true if in real mode, otherwise false.
+ * @param pCtx Current CPU context
+ */
+DECLINLINE(bool) CPUMIsGuestInRealModeEx(PCPUMCTX pCtx)
+{
+ return !(pCtx->cr0 & X86_CR0_PE);
+}
+
+/**
+ * Tests if the guest is running in real or virtual 8086 mode.
+ *
+ * @returns @c true if it is, @c false if not.
+ * @param pCtx Current CPU context
+ */
+DECLINLINE(bool) CPUMIsGuestInRealOrV86ModeEx(PCPUMCTX pCtx)
+{
+ return !(pCtx->cr0 & X86_CR0_PE)
+ || pCtx->eflags.Bits.u1VM; /** @todo verify that this cannot be set in long mode. */
+}
+
+/**
+ * Tests if the guest is running in paged protected or not.
+ *
+ * @returns true if in paged protected mode, otherwise false.
+ * @param pVM The VM handle.
+ */
+DECLINLINE(bool) CPUMIsGuestInPagedProtectedModeEx(PCPUMCTX pCtx)
+{
+ return (pCtx->cr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG);
+}
+
+/**
+ * Tests if the guest is running in long mode or not.
+ *
+ * @returns true if in long mode, otherwise false.
+ * @param pCtx Current CPU context
+ */
+DECLINLINE(bool) CPUMIsGuestInLongModeEx(PCPUMCTX pCtx)
+{
+ return (pCtx->msrEFER & MSR_K6_EFER_LMA) == MSR_K6_EFER_LMA;
+}
+
+VMM_INT_DECL(bool) CPUMIsGuestIn64BitCodeSlow(PCPUMCTX pCtx);
+
+/**
+ * Tests if the guest is running in 64 bits mode or not.
+ *
+ * @returns true if in 64 bits protected mode, otherwise false.
+ * @param pVCpu The current virtual CPU.
+ * @param pCtx Current CPU context
+ */
+DECLINLINE(bool) CPUMIsGuestIn64BitCodeEx(PCPUMCTX pCtx)
+{
+ if (!(pCtx->msrEFER & MSR_K6_EFER_LMA))
+ return false;
+ if (!CPUMSELREG_ARE_HIDDEN_PARTS_VALID(NULL, &pCtx->cs))
+ return CPUMIsGuestIn64BitCodeSlow(pCtx);
+ return pCtx->cs.Attr.n.u1Long;
+}
+
+/**
+ * Tests if the guest is running in PAE mode or not.
+ *
+ * @returns true if in PAE mode, otherwise false.
+ * @param pCtx Current CPU context
+ */
+DECLINLINE(bool) CPUMIsGuestInPAEModeEx(PCPUMCTX pCtx)
+{
+ return ( (pCtx->cr4 & X86_CR4_PAE)
+ && CPUMIsGuestInPagedProtectedModeEx(pCtx)
+ && !CPUMIsGuestInLongModeEx(pCtx));
+}
+
+#endif /* VBOX_WITHOUT_UNNAMED_UNIONS */
+
+/** @} */
+
+
+/** @name Hypervisor Register Getters.
+ * @{ */
+VMMDECL(RTSEL) CPUMGetHyperCS(PVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetHyperDS(PVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetHyperES(PVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetHyperFS(PVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetHyperGS(PVMCPU pVCpu);
+VMMDECL(RTSEL) CPUMGetHyperSS(PVMCPU pVCpu);
+#if 0 /* these are not correct. */
+VMMDECL(uint32_t) CPUMGetHyperCR0(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetHyperCR2(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetHyperCR3(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetHyperCR4(PVMCPU pVCpu);
+#endif
+/** This register is only saved on fatal traps. */
+VMMDECL(uint32_t) CPUMGetHyperEAX(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetHyperEBX(PVMCPU pVCpu);
+/** This register is only saved on fatal traps. */
+VMMDECL(uint32_t) CPUMGetHyperECX(PVMCPU pVCpu);
+/** This register is only saved on fatal traps. */
+VMMDECL(uint32_t) CPUMGetHyperEDX(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetHyperESI(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetHyperEDI(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetHyperEBP(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetHyperESP(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetHyperEFlags(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetHyperEIP(PVMCPU pVCpu);
+VMMDECL(uint64_t) CPUMGetHyperRIP(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetHyperIDTR(PVMCPU pVCpu, uint16_t *pcbLimit);
+VMMDECL(uint32_t) CPUMGetHyperGDTR(PVMCPU pVCpu, uint16_t *pcbLimit);
+VMMDECL(RTSEL) CPUMGetHyperLDTR(PVMCPU pVCpu);
+VMMDECL(RTGCUINTREG) CPUMGetHyperDR0(PVMCPU pVCpu);
+VMMDECL(RTGCUINTREG) CPUMGetHyperDR1(PVMCPU pVCpu);
+VMMDECL(RTGCUINTREG) CPUMGetHyperDR2(PVMCPU pVCpu);
+VMMDECL(RTGCUINTREG) CPUMGetHyperDR3(PVMCPU pVCpu);
+VMMDECL(RTGCUINTREG) CPUMGetHyperDR6(PVMCPU pVCpu);
+VMMDECL(RTGCUINTREG) CPUMGetHyperDR7(PVMCPU pVCpu);
+VMMDECL(void) CPUMGetHyperCtx(PVMCPU pVCpu, PCPUMCTX pCtx);
+VMMDECL(uint32_t) CPUMGetHyperCR3(PVMCPU pVCpu);
+/** @} */
+
+/** @name Hypervisor Register Setters.
+ * @{ */
+VMMDECL(void) CPUMSetHyperGDTR(PVMCPU pVCpu, uint32_t addr, uint16_t limit);
+VMMDECL(void) CPUMSetHyperLDTR(PVMCPU pVCpu, RTSEL SelLDTR);
+VMMDECL(void) CPUMSetHyperIDTR(PVMCPU pVCpu, uint32_t addr, uint16_t limit);
+VMMDECL(void) CPUMSetHyperCR3(PVMCPU pVCpu, uint32_t cr3);
+VMMDECL(void) CPUMSetHyperTR(PVMCPU pVCpu, RTSEL SelTR);
+VMMDECL(void) CPUMSetHyperCS(PVMCPU pVCpu, RTSEL SelCS);
+VMMDECL(void) CPUMSetHyperDS(PVMCPU pVCpu, RTSEL SelDS);
+VMMDECL(void) CPUMSetHyperES(PVMCPU pVCpu, RTSEL SelDS);
+VMMDECL(void) CPUMSetHyperFS(PVMCPU pVCpu, RTSEL SelDS);
+VMMDECL(void) CPUMSetHyperGS(PVMCPU pVCpu, RTSEL SelDS);
+VMMDECL(void) CPUMSetHyperSS(PVMCPU pVCpu, RTSEL SelSS);
+VMMDECL(void) CPUMSetHyperESP(PVMCPU pVCpu, uint32_t u32ESP);
+VMMDECL(int) CPUMSetHyperEFlags(PVMCPU pVCpu, uint32_t Efl);
+VMMDECL(void) CPUMSetHyperEIP(PVMCPU pVCpu, uint32_t u32EIP);
+VMM_INT_DECL(void) CPUMSetHyperState(PVMCPU pVCpu, uint32_t u32EIP, uint32_t u32ESP, uint32_t u32EAX, uint32_t u32EDX);
+VMMDECL(void) CPUMSetHyperDR0(PVMCPU pVCpu, RTGCUINTREG uDr0);
+VMMDECL(void) CPUMSetHyperDR1(PVMCPU pVCpu, RTGCUINTREG uDr1);
+VMMDECL(void) CPUMSetHyperDR2(PVMCPU pVCpu, RTGCUINTREG uDr2);
+VMMDECL(void) CPUMSetHyperDR3(PVMCPU pVCpu, RTGCUINTREG uDr3);
+VMMDECL(void) CPUMSetHyperDR6(PVMCPU pVCpu, RTGCUINTREG uDr6);
+VMMDECL(void) CPUMSetHyperDR7(PVMCPU pVCpu, RTGCUINTREG uDr7);
+VMMDECL(void) CPUMSetHyperCtx(PVMCPU pVCpu, const PCPUMCTX pCtx);
+VMMDECL(int) CPUMRecalcHyperDRx(PVMCPU pVCpu);
+/** @} */
+
+VMMDECL(void) CPUMPushHyper(PVMCPU pVCpu, uint32_t u32);
+VMMDECL(int) CPUMQueryHyperCtxPtr(PVMCPU pVCpu, PCPUMCTX *ppCtx);
+VMMDECL(PCPUMCTX) CPUMGetHyperCtxPtr(PVMCPU pVCpu);
+VMMDECL(PCCPUMCTXCORE) CPUMGetHyperCtxCore(PVMCPU pVCpu);
+VMMDECL(PCPUMCTX) CPUMQueryGuestCtxPtr(PVMCPU pVCpu);
+VMMDECL(PCCPUMCTXCORE) CPUMGetGuestCtxCore(PVMCPU pVCpu);
+VMMR3DECL(int) CPUMR3RawEnter(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore);
+VMMR3DECL(int) CPUMR3RawLeave(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, int rc);
+VMMDECL(uint32_t) CPUMRawGetEFlags(PVMCPU pVCpu);
+VMMDECL(void) CPUMRawSetEFlags(PVMCPU pVCpu, uint32_t fEfl);
+VMMDECL(int) CPUMHandleLazyFPU(PVMCPU pVCpu);
+
+/** @name Changed flags.
+ * These flags are used to keep track of which important register that
+ * have been changed since last they were reset. The only one allowed
+ * to clear them is REM!
+ * @{
+ */
+#define CPUM_CHANGED_FPU_REM RT_BIT(0)
+#define CPUM_CHANGED_CR0 RT_BIT(1)
+#define CPUM_CHANGED_CR4 RT_BIT(2)
+#define CPUM_CHANGED_GLOBAL_TLB_FLUSH RT_BIT(3)
+#define CPUM_CHANGED_CR3 RT_BIT(4)
+#define CPUM_CHANGED_GDTR RT_BIT(5)
+#define CPUM_CHANGED_IDTR RT_BIT(6)
+#define CPUM_CHANGED_LDTR RT_BIT(7)
+#define CPUM_CHANGED_TR RT_BIT(8) /**@< Currently unused. */
+#define CPUM_CHANGED_SYSENTER_MSR RT_BIT(9)
+#define CPUM_CHANGED_HIDDEN_SEL_REGS RT_BIT(10) /**@< Currently unused. */
+#define CPUM_CHANGED_CPUID RT_BIT(11)
+#define CPUM_CHANGED_ALL ( CPUM_CHANGED_FPU_REM \
+ | CPUM_CHANGED_CR0 \
+ | CPUM_CHANGED_CR4 \
+ | CPUM_CHANGED_GLOBAL_TLB_FLUSH \
+ | CPUM_CHANGED_CR3 \
+ | CPUM_CHANGED_GDTR \
+ | CPUM_CHANGED_IDTR \
+ | CPUM_CHANGED_LDTR \
+ | CPUM_CHANGED_TR \
+ | CPUM_CHANGED_SYSENTER_MSR \
+ | CPUM_CHANGED_HIDDEN_SEL_REGS \
+ | CPUM_CHANGED_CPUID )
+/** @} */
+
+VMMDECL(void) CPUMSetChangedFlags(PVMCPU pVCpu, uint32_t fChangedFlags);
+VMMR3DECL(uint32_t) CPUMR3RemEnter(PVMCPU pVCpu, uint32_t *puCpl);
+VMMR3DECL(void) CPUMR3RemLeave(PVMCPU pVCpu, bool fNoOutOfSyncSels);
+VMMDECL(bool) CPUMSupportsFXSR(PVM pVM);
+VMMDECL(bool) CPUMIsHostUsingSysEnter(PVM pVM);
+VMMDECL(bool) CPUMIsHostUsingSysCall(PVM pVM);
+VMMDECL(bool) CPUMIsGuestFPUStateActive(PVMCPU pVCPU);
+VMMDECL(void) CPUMDeactivateGuestFPUState(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsGuestDebugStateActive(PVMCPU pVCpu);
+VMMDECL(void) CPUMDeactivateGuestDebugState(PVMCPU pVCpu);
+VMMDECL(bool) CPUMIsHyperDebugStateActive(PVMCPU pVCpu);
+VMMDECL(void) CPUMDeactivateHyperDebugState(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestCPL(PVMCPU pVCpu);
+VMMDECL(CPUMMODE) CPUMGetGuestMode(PVMCPU pVCpu);
+VMMDECL(uint32_t) CPUMGetGuestCodeBits(PVMCPU pVCpu);
+VMMDECL(DISCPUMODE) CPUMGetGuestDisMode(PVMCPU pVCpu);
+
+
+#ifdef IN_RING3
+/** @defgroup grp_cpum_r3 The CPU Monitor(/Manager) API
+ * @ingroup grp_cpum
+ * @{
+ */
+
+VMMR3DECL(int) CPUMR3Init(PVM pVM);
+VMMR3DECL(void) CPUMR3Relocate(PVM pVM);
+VMMR3DECL(int) CPUMR3Term(PVM pVM);
+VMMR3DECL(void) CPUMR3Reset(PVM pVM);
+VMMR3DECL(void) CPUMR3ResetCpu(PVMCPU pVCpu);
+VMMDECL(bool) CPUMR3IsStateRestorePending(PVM pVM);
+VMMR3DECL(void) CPUMR3SetHWVirtEx(PVM pVM, bool fHWVirtExEnabled);
+VMMR3DECL(int) CPUMR3SetCR4Feature(PVM pVM, RTHCUINTREG fOr, RTHCUINTREG fAnd);
+VMMR3DECL(RCPTRTYPE(PCCPUMCPUID)) CPUMR3GetGuestCpuIdStdRCPtr(PVM pVM);
+VMMR3DECL(RCPTRTYPE(PCCPUMCPUID)) CPUMR3GetGuestCpuIdExtRCPtr(PVM pVM);
+VMMR3DECL(RCPTRTYPE(PCCPUMCPUID)) CPUMR3GetGuestCpuIdCentaurRCPtr(PVM pVM);
+VMMR3DECL(RCPTRTYPE(PCCPUMCPUID)) CPUMR3GetGuestCpuIdDefRCPtr(PVM pVM);
+
+/** @} */
+#endif /* IN_RING3 */
+
+#ifdef IN_RC
+/** @defgroup grp_cpum_gc The CPU Monitor(/Manager) API
+ * @ingroup grp_cpum
+ * @{
+ */
+
+/**
+ * Calls a guest trap/interrupt handler directly
+ *
+ * Assumes a trap stack frame has already been setup on the guest's stack!
+ * This function does not return!
+ *
+ * @param pRegFrame Original trap/interrupt context
+ * @param selCS Code selector of handler
+ * @param pHandler GC virtual address of handler
+ * @param eflags Callee's EFLAGS
+ * @param selSS Stack selector for handler
+ * @param pEsp Stack address for handler
+ */
+DECLASM(void) CPUMGCCallGuestTrapHandler(PCPUMCTXCORE pRegFrame, uint32_t selCS, RTRCPTR pHandler,
+ uint32_t eflags, uint32_t selSS, RTRCPTR pEsp);
+
+/**
+ * Call guest V86 code directly.
+ *
+ * This function does not return!
+ *
+ * @param pRegFrame Original trap/interrupt context
+ */
+DECLASM(void) CPUMGCCallV86Code(PCPUMCTXCORE pRegFrame);
+
+/** @} */
+#endif /* IN_RC */
+
+#ifdef IN_RING0
+/** @defgroup grp_cpum_r0 The CPU Monitor(/Manager) API
+ * @ingroup grp_cpum
+ * @{
+ */
+VMMR0DECL(int) CPUMR0ModuleInit(void);
+VMMR0DECL(int) CPUMR0ModuleTerm(void);
+VMMR0DECL(int) CPUMR0Init(PVM pVM);
+VMMR0DECL(int) CPUMR0LoadGuestFPU(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
+VMMR0DECL(int) CPUMR0SaveGuestFPU(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
+VMMR0DECL(int) CPUMR0SaveGuestDebugState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, bool fDR6);
+VMMR0DECL(int) CPUMR0LoadGuestDebugState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, bool fDR6);
+VMMR0DECL(int) CPUMR0LoadHostDebugState(PVM pVM, PVMCPU pVCpu);
+VMMR0DECL(int) CPUMR0SaveHostDebugState(PVM pVM, PVMCPU pVCpu);
+VMMR0DECL(int) CPUMR0LoadHyperDebugState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, bool fDR6);
+#ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
+VMMR0DECL(void) CPUMR0SetLApic(PVM pVM, RTCPUID idHostCpu);
+#endif
+
+/** @} */
+#endif /* IN_RING0 */
+
+/** @} */
+RT_C_DECLS_END
+
+
+#endif
+
diff --git a/include/VBox/vmm/cpum.mac b/include/VBox/vmm/cpum.mac
new file mode 100644
index 00000000..8f906d06
--- /dev/null
+++ b/include/VBox/vmm/cpum.mac
@@ -0,0 +1,207 @@
+;; @file
+; CPUM - CPU Monitor, Assembly header file.
+;
+
+;
+; Copyright (C) 2006-2010 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; 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.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+; VirtualBox OSE distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+
+%ifndef ___VBox_vmm_cpum_mac__
+%define ___VBox_vmm_cpum_mac__
+
+;;
+; Registers frame.
+; This is used internally in TRPM, VMMSwitcher_GuestToHost_GuestCtx
+; and other places.
+struc CPUMCTXCORE
+ .eax resq 1
+ .ecx resq 1
+ .edx resq 1
+ .ebx resq 1
+ .esp resq 1
+ .ebp resq 1
+ .esi resq 1
+ .edi resq 1
+ .r8 resq 1
+ .r9 resq 1
+ .r10 resq 1
+ .r11 resq 1
+ .r12 resq 1
+ .r13 resq 1
+ .r14 resq 1
+ .r15 resq 1
+ .es.Sel resw 1
+ .es.PaddingSel resw 1
+ .es.ValidSel resw 1
+ .es.fFlags resw 1
+ .es.u64Base resq 1
+ .es.u32Limit resd 1
+ .es.Attr resd 1
+ .cs.Sel resw 1
+ .cs.PaddingSel resw 1
+ .cs.ValidSel resw 1
+ .cs.fFlags resw 1
+ .cs.u64Base resq 1
+ .cs.u32Limit resd 1
+ .cs.Attr resd 1
+ .ss.Sel resw 1
+ .ss.PaddingSel resw 1
+ .ss.ValidSel resw 1
+ .ss.fFlags resw 1
+ .ss.u64Base resq 1
+ .ss.u32Limit resd 1
+ .ss.Attr resd 1
+ .ds.Sel resw 1
+ .ds.PaddingSel resw 1
+ .ds.ValidSel resw 1
+ .ds.fFlags resw 1
+ .ds.u64Base resq 1
+ .ds.u32Limit resd 1
+ .ds.Attr resd 1
+ .fs.Sel resw 1
+ .fs.PaddingSel resw 1
+ .fs.ValidSel resw 1
+ .fs.fFlags resw 1
+ .fs.u64Base resq 1
+ .fs.u32Limit resd 1
+ .fs.Attr resd 1
+ .gs.Sel resw 1
+ .gs.PaddingSel resw 1
+ .gs.ValidSel resw 1
+ .gs.fFlags resw 1
+ .gs.u64Base resq 1
+ .gs.u32Limit resd 1
+ .gs.Attr resd 1
+ .eip resq 1
+ .eflags resq 1
+endstruc
+
+
+struc CPUMCTX
+ .fpu resb 512
+ .eax resq 1
+ .ecx resq 1
+ .edx resq 1
+ .ebx resq 1
+ .esp resq 1
+ .ebp resq 1
+ .esi resq 1
+ .edi resq 1
+ .r8 resq 1
+ .r9 resq 1
+ .r10 resq 1
+ .r11 resq 1
+ .r12 resq 1
+ .r13 resq 1
+ .r14 resq 1
+ .r15 resq 1
+ .es.Sel resw 1
+ .es.PaddingSel resw 1
+ .es.ValidSel resw 1
+ .es.fFlags resw 1
+ .es.u64Base resq 1
+ .es.u32Limit resd 1
+ .es.Attr resd 1
+ .cs.Sel resw 1
+ .cs.PaddingSel resw 1
+ .cs.ValidSel resw 1
+ .cs.fFlags resw 1
+ .cs.u64Base resq 1
+ .cs.u32Limit resd 1
+ .cs.Attr resd 1
+ .ss.Sel resw 1
+ .ss.PaddingSel resw 1
+ .ss.ValidSel resw 1
+ .ss.fFlags resw 1
+ .ss.u64Base resq 1
+ .ss.u32Limit resd 1
+ .ss.Attr resd 1
+ .ds.Sel resw 1
+ .ds.PaddingSel resw 1
+ .ds.ValidSel resw 1
+ .ds.fFlags resw 1
+ .ds.u64Base resq 1
+ .ds.u32Limit resd 1
+ .ds.Attr resd 1
+ .fs.Sel resw 1
+ .fs.PaddingSel resw 1
+ .fs.ValidSel resw 1
+ .fs.fFlags resw 1
+ .fs.u64Base resq 1
+ .fs.u32Limit resd 1
+ .fs.Attr resd 1
+ .gs.Sel resw 1
+ .gs.PaddingSel resw 1
+ .gs.ValidSel resw 1
+ .gs.fFlags resw 1
+ .gs.u64Base resq 1
+ .gs.u32Limit resd 1
+ .gs.Attr resd 1
+ .eip resq 1
+ .eflags resq 1
+ .cr0 resq 1
+ .cr2 resq 1
+ .cr3 resq 1
+ .cr4 resq 1
+ .dr resq 8
+ .gdtrPadding resw 3
+ .gdtr resw 0
+ .gdtr.cbGdt resw 1
+ .gdtr.pGdt resq 1
+ .idtrPadding resw 3
+ .idtr resw 0
+ .idtr.cbIdt resw 1
+ .idtr.pIdt resq 1
+ .ldtr.Sel resw 1
+ .ldtr.PaddingSel resw 1
+ .ldtr.ValidSel resw 1
+ .ldtr.fFlags resw 1
+ .ldtr.u64Base resq 1
+ .ldtr.u32Limit resd 1
+ .ldtr.Attr resd 1
+ .tr.Sel resw 1
+ .tr.PaddingSel resw 1
+ .tr.ValidSel resw 1
+ .tr.fFlags resw 1
+ .tr.u64Base resq 1
+ .tr.u32Limit resd 1
+ .tr.Attr resd 1
+ .SysEnter.cs resb 8
+ .SysEnter.eip resb 8
+ .SysEnter.esp resb 8
+ .msrEFER resb 8
+ .msrSTAR resb 8
+ .msrPAT resb 8
+ .msrLSTAR resb 8
+ .msrCSTAR resb 8
+ .msrSFMASK resb 8
+ .msrKERNELGSBASE resb 8
+ .au32SizePadding resb 32
+endstruc
+
+
+;;
+; Guest MSR state.
+struc CPUMCTXMSRS
+ .au64 resq 64
+endstruc
+
+
+%endif
diff --git a/include/VBox/vmm/cpumctx-v1_6.h b/include/VBox/vmm/cpumctx-v1_6.h
new file mode 100644
index 00000000..dbc5935d
--- /dev/null
+++ b/include/VBox/vmm/cpumctx-v1_6.h
@@ -0,0 +1,249 @@
+/** @file
+ * CPUM - CPU Monitor(/ Manager), Context Structures from v1.6 (saved state).
+ */
+
+/*
+ * Copyright (C) 2006-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_cpumctx_v1_6_h
+#define ___VBox_vmm_cpumctx_v1_6_h
+
+#include <iprt/x86.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @addgroup grp_cpum_ctx_v1_6 The CPUM Context Structures from v1.6
+ * @ingroup grp_cpum
+ * @{
+ */
+
+#pragma pack(1)
+/** IDTR from version 1.6 */
+typedef struct VBOXIDTR_VER1_6
+{
+ /** Size of the IDT. */
+ uint16_t cbIdt;
+ /** Address of the IDT. */
+ uint32_t pIdt;
+} VBOXIDTR_VER1_6;
+#pragma pack()
+
+#pragma pack(1)
+/** GDTR from version 1.6 */
+typedef struct VBOXGDTR_VER1_6
+{
+ /** Size of the GDT. */
+ uint16_t cbGdt;
+ /** Address of the GDT. */
+ uint32_t pGdt;
+} VBOXGDTR_VER1_6;
+#pragma pack()
+
+
+/**
+ * Selector hidden registers, for version 1.6 saved state.
+ */
+typedef struct CPUMSELREGHID_VER1_6
+{
+ /** Base register. */
+ uint32_t u32Base;
+ /** Limit (expanded). */
+ uint32_t u32Limit;
+ /** Flags.
+ * This is the high 32-bit word of the descriptor entry.
+ * Only the flags, dpl and type are used. */
+ X86DESCATTR Attr;
+} CPUMSELREGHID_VER1_6;
+
+/**
+ * CPU context, for version 1.6 saved state.
+ * @remarks PATM uses this, which is why it has to be here.
+ */
+# pragma pack(1)
+typedef struct CPUMCTX_VER1_6
+{
+ /** FPU state. (16-byte alignment)
+ * @todo This doesn't have to be in X86FXSTATE on CPUs without fxsr - we need a type for the
+ * actual format or convert it (waste of time). */
+ X86FXSTATE fpu;
+
+ /** CPUMCTXCORE Part.
+ * @{ */
+ union
+ {
+ uint32_t edi;
+ uint64_t rdi;
+ } CPUM_UNION_NAME(rdi);
+ union
+ {
+ uint32_t esi;
+ uint64_t rsi;
+ } CPUM_UNION_NAME(rsi);
+ union
+ {
+ uint32_t ebp;
+ uint64_t rbp;
+ } CPUM_UNION_NAME(rbp);
+ union
+ {
+ uint32_t eax;
+ uint64_t rax;
+ } CPUM_UNION_NAME(rax);
+ union
+ {
+ uint32_t ebx;
+ uint64_t rbx;
+ } CPUM_UNION_NAME(rbx);
+ union
+ {
+ uint32_t edx;
+ uint64_t rdx;
+ } CPUM_UNION_NAME(rdx);
+ union
+ {
+ uint32_t ecx;
+ uint64_t rcx;
+ } CPUM_UNION_NAME(rcx);
+ /** @note We rely on the exact layout, because we use lss esp, [] in the
+ * switcher. */
+ uint32_t esp;
+ RTSEL ss;
+ RTSEL ssPadding;
+ /* Note: no overlap with esp here. */
+ uint64_t rsp_notused;
+
+ RTSEL gs;
+ RTSEL gsPadding;
+ RTSEL fs;
+ RTSEL fsPadding;
+ RTSEL es;
+ RTSEL esPadding;
+ RTSEL ds;
+ RTSEL dsPadding;
+ RTSEL cs;
+ RTSEL csPadding[3]; /**< 3 words to force 8 byte alignment for the remainder. */
+
+ union
+ {
+ X86EFLAGS eflags;
+ X86RFLAGS rflags;
+ } CPUM_UNION_NAME(rflags);
+ union
+ {
+ uint32_t eip;
+ uint64_t rip;
+ } CPUM_UNION_NAME(rip);
+
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+
+ /** Hidden selector registers.
+ * @{ */
+ CPUMSELREGHID_VER1_6 esHid;
+ CPUMSELREGHID_VER1_6 csHid;
+ CPUMSELREGHID_VER1_6 ssHid;
+ CPUMSELREGHID_VER1_6 dsHid;
+ CPUMSELREGHID_VER1_6 fsHid;
+ CPUMSELREGHID_VER1_6 gsHid;
+ /** @} */
+
+ /** @} */
+
+ /** Control registers.
+ * @{ */
+ uint64_t cr0;
+ uint64_t cr2;
+ uint64_t cr3;
+ uint64_t cr4;
+ uint64_t cr8;
+ /** @} */
+
+ /** Debug registers.
+ * @{ */
+ uint64_t dr0;
+ uint64_t dr1;
+ uint64_t dr2;
+ uint64_t dr3;
+ uint64_t dr4; /**< @todo remove dr4 and dr5. */
+ uint64_t dr5;
+ uint64_t dr6;
+ uint64_t dr7;
+ /* DR8-15 are currently not supported */
+ /** @} */
+
+ /** Global Descriptor Table register. */
+ VBOXGDTR_VER1_6 gdtr;
+ uint16_t gdtrPadding;
+ uint32_t gdtrPadding64;/** @todo fix this hack */
+ /** Interrupt Descriptor Table register. */
+ VBOXIDTR_VER1_6 idtr;
+ uint16_t idtrPadding;
+ uint32_t idtrPadding64;/** @todo fix this hack */
+ /** The task register.
+ * Only the guest context uses all the members. */
+ RTSEL ldtr;
+ RTSEL ldtrPadding;
+ /** The task register.
+ * Only the guest context uses all the members. */
+ RTSEL tr;
+ RTSEL trPadding;
+
+ /** The sysenter msr registers.
+ * This member is not used by the hypervisor context. */
+ CPUMSYSENTER SysEnter;
+
+ /** System MSRs.
+ * @{ */
+ uint64_t msrEFER;
+ uint64_t msrSTAR;
+ uint64_t msrPAT;
+ uint64_t msrLSTAR;
+ uint64_t msrCSTAR;
+ uint64_t msrSFMASK;
+ uint64_t msrFSBASE;
+ uint64_t msrGSBASE;
+ uint64_t msrKERNELGSBASE;
+ /** @} */
+
+ /** Hidden selector registers.
+ * @{ */
+ CPUMSELREGHID_VER1_6 ldtrHid;
+ CPUMSELREGHID_VER1_6 trHid;
+ /** @} */
+
+ /** padding to get 32byte aligned size. */
+ uint32_t padding[2];
+} CPUMCTX_VER1_6;
+# pragma pack()
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/cpumctx.h b/include/VBox/vmm/cpumctx.h
new file mode 100644
index 00000000..35861823
--- /dev/null
+++ b/include/VBox/vmm/cpumctx.h
@@ -0,0 +1,477 @@
+/** @file
+ * CPUM - CPU Monitor(/ Manager), Context Structures.
+ */
+
+/*
+ * Copyright (C) 2006-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_cpumctx_h
+#define ___VBox_vmm_cpumctx_h
+
+#ifndef VBOX_FOR_DTRACE_LIB
+# include <iprt/x86.h>
+# include <VBox/types.h>
+#else
+# pragma D depends_on library x86.d
+#endif
+
+
+RT_C_DECLS_BEGIN
+
+/** @addgroup grp_cpum_ctx The CPUM Context Structures
+ * @ingroup grp_cpum
+ * @{
+ */
+
+/**
+ * Selector hidden registers.
+ */
+typedef struct CPUMSELREG
+{
+ /** The selector register. */
+ RTSEL Sel;
+ /** Padding, don't use. */
+ RTSEL PaddingSel;
+ /** The selector which info resides in u64Base, u32Limit and Attr, provided
+ * that CPUMSELREG_FLAGS_VALID is set. */
+ RTSEL ValidSel;
+ /** Flags, see CPUMSELREG_FLAGS_XXX. */
+ uint16_t fFlags;
+
+ /** Base register.
+ *
+ * Long mode remarks:
+ * - Unused in long mode for CS, DS, ES, SS
+ * - 32 bits for FS & GS; FS(GS)_BASE msr used for the base address
+ * - 64 bits for TR & LDTR
+ */
+ uint64_t u64Base;
+ /** Limit (expanded). */
+ uint32_t u32Limit;
+ /** Flags.
+ * This is the high 32-bit word of the descriptor entry.
+ * Only the flags, dpl and type are used. */
+ X86DESCATTR Attr;
+} CPUMSELREG;
+
+/** @name CPUMSELREG_FLAGS_XXX - CPUMSELREG::fFlags values.
+ * @{ */
+#define CPUMSELREG_FLAGS_VALID UINT16_C(0x0001)
+#define CPUMSELREG_FLAGS_STALE UINT16_C(0x0002)
+#define CPUMSELREG_FLAGS_VALID_MASK UINT16_C(0x0003)
+/** @} */
+
+/** Checks if the hidden parts of the selector register are valid. */
+#ifdef VBOX_WITH_RAW_MODE_NOT_R0
+# define CPUMSELREG_ARE_HIDDEN_PARTS_VALID(a_pVCpu, a_pSelReg) \
+ ( ((a_pSelReg)->fFlags & CPUMSELREG_FLAGS_VALID) \
+ && ( (a_pSelReg)->ValidSel == (a_pSelReg)->Sel \
+ || ( (a_pVCpu) /*!= NULL*/ \
+ && (a_pSelReg)->ValidSel == ((a_pSelReg)->Sel & X86_SEL_MASK_OFF_RPL) \
+ && ((a_pSelReg)->Sel & X86_SEL_RPL) == 1 \
+ && ((a_pSelReg)->ValidSel & X86_SEL_RPL) == 0 \
+ && CPUMIsGuestInRawMode(a_pVCpu) \
+ ) \
+ ) \
+ )
+#else
+# define CPUMSELREG_ARE_HIDDEN_PARTS_VALID(a_pVCpu, a_pSelReg) \
+ ( ((a_pSelReg)->fFlags & CPUMSELREG_FLAGS_VALID) \
+ && (a_pSelReg)->ValidSel == (a_pSelReg)->Sel )
+#endif
+
+/** Old type used for the hidden register part.
+ * @deprecated */
+typedef CPUMSELREG CPUMSELREGHID;
+
+/**
+ * The sysenter register set.
+ */
+typedef struct CPUMSYSENTER
+{
+ /** Ring 0 cs.
+ * This value + 8 is the Ring 0 ss.
+ * This value + 16 is the Ring 3 cs.
+ * This value + 24 is the Ring 3 ss.
+ */
+ uint64_t cs;
+ /** Ring 0 eip. */
+ uint64_t eip;
+ /** Ring 0 esp. */
+ uint64_t esp;
+} CPUMSYSENTER;
+
+/**
+ * For compilers (like DTrace) that does not grok nameless unions, we have a
+ * little hack to make them palatable.
+ */
+#ifdef VBOX_FOR_DTRACE_LIB
+# define CPUM_UNION_NAME(a_Nm) a_Nm
+#elif defined(VBOX_WITHOUT_UNNAMED_UNIONS)
+# define CPUM_UNION_NAME(a_Nm) a_Nm
+#else
+# define CPUM_UNION_NAME(a_Nm)
+#endif
+
+
+/**
+ * CPU context core.
+ *
+ * @todo eliminate this structure!
+ */
+#pragma pack(1)
+typedef struct CPUMCTXCORE
+{
+ /** @name General Register.
+ * @note These follow the encoding order (X86_GREG_XXX) and can be accessed as
+ * an array starting a rax.
+ * @{ */
+ union
+ {
+ uint8_t al;
+ uint16_t ax;
+ uint32_t eax;
+ uint64_t rax;
+ } CPUM_UNION_NAME(rax);
+ union
+ {
+ uint8_t cl;
+ uint16_t cx;
+ uint32_t ecx;
+ uint64_t rcx;
+ } CPUM_UNION_NAME(rcx);
+ union
+ {
+ uint8_t dl;
+ uint16_t dx;
+ uint32_t edx;
+ uint64_t rdx;
+ } CPUM_UNION_NAME(rdx);
+ union
+ {
+ uint8_t bl;
+ uint16_t bx;
+ uint32_t ebx;
+ uint64_t rbx;
+ } CPUM_UNION_NAME(rbx);
+ union
+ {
+ uint16_t sp;
+ uint32_t esp;
+ uint64_t rsp;
+ } CPUM_UNION_NAME(rsp);
+ union
+ {
+ uint16_t bp;
+ uint32_t ebp;
+ uint64_t rbp;
+ } CPUM_UNION_NAME(rbp);
+ union
+ {
+ uint8_t sil;
+ uint16_t si;
+ uint32_t esi;
+ uint64_t rsi;
+ } CPUM_UNION_NAME(rsi);
+ union
+ {
+ uint8_t dil;
+ uint16_t di;
+ uint32_t edi;
+ uint64_t rdi;
+ } CPUM_UNION_NAME(rdi);
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ /** @} */
+
+ /** @name Segment registers.
+ * @note These follow the encoding order (X86_SREG_XXX) and can be accessed as
+ * an array starting a es.
+ * @{ */
+ CPUMSELREG es;
+ CPUMSELREG cs;
+ CPUMSELREG ss;
+ CPUMSELREG ds;
+ CPUMSELREG fs;
+ CPUMSELREG gs;
+ /** @} */
+
+ /** The program counter. */
+ union
+ {
+ uint16_t ip;
+ uint32_t eip;
+ uint64_t rip;
+ } CPUM_UNION_NAME(rip);
+
+ /** The flags register. */
+ union
+ {
+ X86EFLAGS eflags;
+ X86RFLAGS rflags;
+ } CPUM_UNION_NAME(rflags);
+
+} CPUMCTXCORE;
+#pragma pack()
+
+
+/**
+ * CPU context.
+ */
+#pragma pack(1) /* for VBOXIDTR / VBOXGDTR. */
+typedef struct CPUMCTX
+{
+ /** FPU state. (16-byte alignment)
+ * @todo This doesn't have to be in X86FXSTATE on CPUs without fxsr - we need a type for the
+ * actual format or convert it (waste of time). */
+ X86FXSTATE fpu;
+
+ /** CPUMCTXCORE Part.
+ * @{ */
+
+ /** @name General Register.
+ * @note These follow the encoding order (X86_GREG_XXX) and can be accessed as
+ * an array starting at rax.
+ * @{ */
+ union
+ {
+ uint8_t al;
+ uint16_t ax;
+ uint32_t eax;
+ uint64_t rax;
+ } CPUM_UNION_NAME(rax);
+ union
+ {
+ uint8_t cl;
+ uint16_t cx;
+ uint32_t ecx;
+ uint64_t rcx;
+ } CPUM_UNION_NAME(rcx);
+ union
+ {
+ uint8_t dl;
+ uint16_t dx;
+ uint32_t edx;
+ uint64_t rdx;
+ } CPUM_UNION_NAME(rdx);
+ union
+ {
+ uint8_t bl;
+ uint16_t bx;
+ uint32_t ebx;
+ uint64_t rbx;
+ } CPUM_UNION_NAME(rbx);
+ union
+ {
+ uint16_t sp;
+ uint32_t esp;
+ uint64_t rsp;
+ } CPUM_UNION_NAME(rsp);
+ union
+ {
+ uint16_t bp;
+ uint32_t ebp;
+ uint64_t rbp;
+ } CPUM_UNION_NAME(rbp);
+ union
+ {
+ uint8_t sil;
+ uint16_t si;
+ uint32_t esi;
+ uint64_t rsi;
+ } CPUM_UNION_NAME(rsi);
+ union
+ {
+ uint8_t dil;
+ uint16_t di;
+ uint32_t edi;
+ uint64_t rdi;
+ } CPUM_UNION_NAME(rdi);
+ uint64_t r8;
+ uint64_t r9;
+ uint64_t r10;
+ uint64_t r11;
+ uint64_t r12;
+ uint64_t r13;
+ uint64_t r14;
+ uint64_t r15;
+ /** @} */
+
+ /** @name Segment registers.
+ * @note These follow the encoding order (X86_SREG_XXX) and can be accessed as
+ * an array starting at es.
+ * @{ */
+ CPUMSELREG es;
+ CPUMSELREG cs;
+ CPUMSELREG ss;
+ CPUMSELREG ds;
+ CPUMSELREG fs;
+ CPUMSELREG gs;
+ /** @} */
+
+ /** The program counter. */
+ union
+ {
+ uint16_t ip;
+ uint32_t eip;
+ uint64_t rip;
+ } CPUM_UNION_NAME(rip);
+
+ /** The flags register. */
+ union
+ {
+ X86EFLAGS eflags;
+ X86RFLAGS rflags;
+ } CPUM_UNION_NAME(rflags);
+
+ /** @} */ /*(CPUMCTXCORE)*/
+
+
+ /** @name Control registers.
+ * @{ */
+ uint64_t cr0;
+ uint64_t cr2;
+ uint64_t cr3;
+ uint64_t cr4;
+ /** @} */
+
+ /** Debug registers.
+ * @remarks DR4 and DR5 should not be used since they are aliases for
+ * DR6 and DR7 respectively on both AMD and Intel CPUs.
+ * @remarks DR8-15 are currently not supported by AMD or Intel, so
+ * neither do we.
+ */
+ uint64_t dr[8];
+
+ /** Padding before the structure so the 64-bit member is correctly aligned.
+ * @todo fix this structure! */
+ uint16_t gdtrPadding[3];
+ /** Global Descriptor Table register. */
+ VBOXGDTR gdtr;
+
+ /** Padding before the structure so the 64-bit member is correctly aligned.
+ * @todo fix this structure! */
+ uint16_t idtrPadding[3];
+ /** Interrupt Descriptor Table register. */
+ VBOXIDTR idtr;
+
+ /** The task register.
+ * Only the guest context uses all the members. */
+ CPUMSELREG ldtr;
+ /** The task register.
+ * Only the guest context uses all the members. */
+ CPUMSELREG tr;
+
+ /** The sysenter msr registers.
+ * This member is not used by the hypervisor context. */
+ CPUMSYSENTER SysEnter;
+
+ /** @name System MSRs.
+ * @{ */
+ uint64_t msrEFER;
+ uint64_t msrSTAR; /**< Legacy syscall eip, cs & ss. */
+ uint64_t msrPAT; /**< Page attribute table. */
+ uint64_t msrLSTAR; /**< 64 bits mode syscall rip. */
+ uint64_t msrCSTAR; /**< Compatibility mode syscall rip. */
+ uint64_t msrSFMASK; /**< syscall flag mask. */
+ uint64_t msrKERNELGSBASE; /**< swapgs exchange value. */
+ /** @} */
+
+ /** Size padding. */
+ uint32_t au32SizePadding[8];
+} CPUMCTX;
+#pragma pack()
+
+#ifndef VBOX_FOR_DTRACE_LIB
+
+/**
+ * Gets the CPUMCTXCORE part of a CPUMCTX.
+ */
+# define CPUMCTX2CORE(pCtx) ((PCPUMCTXCORE)(void *)&(pCtx)->rax)
+
+/**
+ * Gets the first selector register of a CPUMCTX.
+ *
+ * Use this with X86_SREG_COUNT to loop thru the selector registers.
+ */
+# define CPUMCTX_FIRST_SREG(a_pCtx) (&(a_pCtx)->es)
+
+#endif /* !VBOX_FOR_DTRACE_LIB */
+
+/**
+ * Additional guest MSRs (i.e. not part of the CPU context structure).
+ *
+ * @remarks Never change the order here because of the saved stated! The size
+ * can in theory be changed, but keep older VBox versions in mind.
+ */
+typedef union CPUMCTXMSRS
+{
+ struct
+ {
+ uint64_t TscAux; /**< MSR_K8_TSC_AUX */
+ uint64_t MiscEnable; /**< MSR_IA32_MISC_ENABLE */
+ uint64_t MtrrDefType; /**< IA32_MTRR_DEF_TYPE */
+ uint64_t MtrrFix64K_00000; /**< IA32_MTRR_FIX16K_80000 */
+ uint64_t MtrrFix16K_80000; /**< IA32_MTRR_FIX16K_80000 */
+ uint64_t MtrrFix16K_A0000; /**< IA32_MTRR_FIX16K_A0000 */
+ uint64_t MtrrFix4K_C0000; /**< IA32_MTRR_FIX4K_C0000 */
+ uint64_t MtrrFix4K_C8000; /**< IA32_MTRR_FIX4K_C8000 */
+ uint64_t MtrrFix4K_D0000; /**< IA32_MTRR_FIX4K_D0000 */
+ uint64_t MtrrFix4K_D8000; /**< IA32_MTRR_FIX4K_D8000 */
+ uint64_t MtrrFix4K_E0000; /**< IA32_MTRR_FIX4K_E0000 */
+ uint64_t MtrrFix4K_E8000; /**< IA32_MTRR_FIX4K_E8000 */
+ uint64_t MtrrFix4K_F0000; /**< IA32_MTRR_FIX4K_F0000 */
+ uint64_t MtrrFix4K_F8000; /**< IA32_MTRR_FIX4K_F8000 */
+ } msr;
+ uint64_t au64[64];
+} CPUMCTXMSRS;
+/** Pointer to the guest MSR state. */
+typedef CPUMCTXMSRS *PCPUMCTXMSRS;
+/** Pointer to the const guest MSR state. */
+typedef const CPUMCTXMSRS *PCCPUMCTXMSRS;
+
+/**
+ * The register set returned by a CPUID operation.
+ */
+typedef struct CPUMCPUID
+{
+ uint32_t eax;
+ uint32_t ebx;
+ uint32_t ecx;
+ uint32_t edx;
+} CPUMCPUID;
+/** Pointer to a CPUID leaf. */
+typedef CPUMCPUID *PCPUMCPUID;
+/** Pointer to a const CPUID leaf. */
+typedef const CPUMCPUID *PCCPUMCPUID;
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/cpumdis.h b/include/VBox/vmm/cpumdis.h
new file mode 100644
index 00000000..9aa509a3
--- /dev/null
+++ b/include/VBox/vmm/cpumdis.h
@@ -0,0 +1,48 @@
+/** @file
+ * CPUM - Disassembler.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_cpumdis_h
+#define ___VBox_vmm_cpumdis_h
+
+#include <VBox/vmm/cpum.h>
+#include <iprt/x86.h>
+#include <VBox/dis.h>
+
+
+RT_C_DECLS_BEGIN
+/** @addtogroup grp_cpum
+ * @{
+ */
+
+#ifdef IN_RING3
+VMMR3DECL(int) CPUMR3DisasmInstrCPU(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx, RTGCPTR GCPtrPC, PDISCPUSTATE pCpu, const char *pszPrefix);
+#endif
+
+/** @} */
+RT_C_DECLS_END
+
+
+#endif
+
diff --git a/include/VBox/vmm/csam.h b/include/VBox/vmm/csam.h
new file mode 100644
index 00000000..675cac7f
--- /dev/null
+++ b/include/VBox/vmm/csam.h
@@ -0,0 +1,305 @@
+/** @file
+ * CSAM - Guest OS Code Scanning and Analyis Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_csam_h
+#define ___VBox_vmm_csam_h
+
+#include <VBox/types.h>
+
+
+/** @defgroup grp_csam The Code Scanning and Analysis API
+ * @{
+ */
+
+/**
+ * CSAM monitoring tag
+ * For use with CSAMR3MonitorPage
+ */
+typedef enum CSAMTAG
+{
+ CSAM_TAG_INVALID = 0,
+ CSAM_TAG_REM,
+ CSAM_TAG_PATM,
+ CSAM_TAG_CSAM,
+ CSAM_TAG_32BIT_HACK = 0x7fffffff
+} CSAMTAG;
+
+
+RT_C_DECLS_BEGIN
+
+
+/**
+ * Check if this page needs to be analysed by CSAM.
+ *
+ * This function should only be called for supervisor pages and
+ * only when CSAM is enabled. Leaving these selection criteria
+ * to the caller simplifies the interface (PTE passing).
+ *
+ * Note the the page has not yet been synced, so the TLB trick
+ * (which wasn't ever active anyway) cannot be applied.
+ *
+ * @returns true if the page should be marked not present because
+ * CSAM want need to scan it.
+ * @returns false if the page was already scanned.
+ * @param pVM The VM to operate on.
+ * @param GCPtr GC pointer of page table entry
+ */
+VMMDECL(bool) CSAMDoesPageNeedScanning(PVM pVM, RTRCUINTPTR GCPtr);
+
+/**
+ * Check if this page was previously scanned by CSAM
+ *
+ * @returns true -> scanned, false -> not scanned
+ * @param pVM The VM to operate on.
+ * @param pPage GC page address
+ */
+VMMDECL(bool) CSAMIsPageScanned(PVM pVM, RTRCPTR pPage);
+
+/**
+ * Mark a page as scanned/not scanned
+ *
+ * @note: we always mark it as scanned, even if we haven't completely done so
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pPage GC page address (not necessarily aligned)
+ * @param fScanned Mark as scanned or not scanned
+ *
+ */
+VMMDECL(int) CSAMMarkPage(PVM pVM, RTRCUINTPTR pPage, bool fScanned);
+
+
+/**
+ * Remember a possible code page for later inspection
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param GCPtr GC pointer of page
+ */
+VMMDECL(void) CSAMMarkPossibleCodePage(PVM pVM, RTRCPTR GCPtr);
+
+/**
+ * Query CSAM state (enabled/disabled)
+ *
+ * @returns 0 - disabled, 1 - enabled
+ * @param pVM The VM to operate on.
+ */
+#define CSAMIsEnabled(pVM) (pVM->fCSAMEnabled && EMIsRawRing0Enabled(pVM))
+
+/**
+ * Turn on code scanning
+ *
+ * @returns VBox status code. (trap handled or not)
+ * @param pVM The VM to operate on.
+ */
+VMMDECL(int) CSAMEnableScanning(PVM pVM);
+
+/**
+ * Turn off code scanning
+ *
+ * @returns VBox status code. (trap handled or not)
+ * @param pVM The VM to operate on.
+ */
+VMMDECL(int) CSAMDisableScanning(PVM pVM);
+
+
+/**
+ * Check if this page needs to be analysed by CSAM
+ *
+ * @returns 0 - disabled, 1 - enabled
+ * @param pVM The VM to operate on.
+ * @param pvFault Fault address
+ */
+VMMDECL(int) CSAMExecFault(PVM pVM, RTRCPTR pvFault);
+
+/**
+ * Check if we've scanned this instruction before. If true, then we can emulate
+ * it instead of returning to ring 3.
+ *
+ * @returns boolean
+ * @param pVM The VM to operate on.
+ * @param GCPtr GC pointer of page table entry
+ */
+VMMDECL(bool) CSAMIsKnownDangerousInstr(PVM pVM, RTRCUINTPTR GCPtr);
+
+
+#ifdef IN_RING3
+/** @defgroup grp_csam_r3 The Code Scanning and Analysis API
+ * @ingroup grp_csam
+ * @{
+ */
+
+/**
+ * Query CSAM state (enabled/disabled)
+ *
+ * @returns 0 - disabled, 1 - enabled
+ * @param pVM The VM to operate on.
+ */
+VMMR3DECL(int) CSAMR3IsEnabled(PVM pVM);
+
+/**
+ * Initializes the csam.
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ */
+VMMR3DECL(int) CSAMR3Init(PVM pVM);
+
+/**
+ * Applies relocations to data and code managed by this
+ * component. This function will be called at init and
+ * whenever the VMM need to relocate it self inside the GC.
+ *
+ * The csam will update the addresses used by the switcher.
+ *
+ * @param pVM The VM.
+ * @param offDelta Relocation delta.
+ */
+VMMR3DECL(void) CSAMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+
+/**
+ * Terminates the csam.
+ *
+ * Termination means cleaning up and freeing all resources,
+ * the VM it self is at this point powered off or suspended.
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ */
+VMMR3DECL(int) CSAMR3Term(PVM pVM);
+
+/**
+ * CSAM reset callback.
+ *
+ * @returns VBox status code.
+ * @param pVM The VM which is reset.
+ */
+VMMR3DECL(int) CSAMR3Reset(PVM pVM);
+
+
+/**
+ * Notify CSAM of a page flush
+ *
+ * @returns VBox status code
+ * @param pVM The VM to operate on.
+ * @param addr GC address of the page to flush
+ */
+VMMR3DECL(int) CSAMR3FlushPage(PVM pVM, RTRCPTR addr);
+
+/**
+ * Remove a CSAM monitored page. Use with care!
+ *
+ * @returns VBox status code
+ * @param pVM The VM to operate on.
+ * @param addr GC address of the page to flush
+ */
+VMMR3DECL(int) CSAMR3RemovePage(PVM pVM, RTRCPTR addr);
+
+/**
+ * Scan and analyse code
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pCtxCore CPU context
+ * @param pInstrGC Instruction pointer
+ */
+VMMR3DECL(int) CSAMR3CheckCodeEx(PVM pVM, PCPUMCTXCORE pCtxCore, RTRCPTR pInstrGC);
+
+/**
+ * Scan and analyse code
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pInstrGC Instruction pointer (0:32 virtual address)
+ */
+VMMR3DECL(int) CSAMR3CheckCode(PVM pVM, RTRCPTR pInstrGC);
+
+/**
+ * Mark an instruction in a page as scanned/not scanned
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pInstr Instruction pointer
+ * @param cbInstr Instruction size
+ * @param fScanned Mark as scanned or not
+ */
+VMMR3DECL(int) CSAMR3MarkCode(PVM pVM, RTRCPTR pInstr, uint32_t cbInstr, bool fScanned);
+
+/**
+ * Perform any pending actions
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pVCpu The VMCPU to operate on.
+ */
+VMMR3DECL(int) CSAMR3DoPendingAction(PVM pVM, PVMCPU pVCpu);
+
+/**
+ * Monitors a code page (if not already monitored)
+ *
+ * @returns VBox status code
+ * @param pVM The VM to operate on.
+ * @param pPageAddrGC The page to monitor
+ * @param enmTag Monitor tag
+ */
+VMMR3DECL(int) CSAMR3MonitorPage(PVM pVM, RTRCPTR pPageAddrGC, CSAMTAG enmTag);
+
+/**
+ * Unmonitors a code page
+ *
+ * @returns VBox status code
+ * @param pVM The VM to operate on.
+ * @param pPageAddrGC The page to monitor
+ * @param enmTag Monitor tag
+ */
+VMMR3DECL(int) CSAMR3UnmonitorPage(PVM pVM, RTRCPTR pPageAddrGC, CSAMTAG enmTag);
+
+/**
+ * Analyse interrupt and trap gates
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param iGate Start gate
+ * @param cGates Number of gates to check
+ */
+VMMR3DECL(int) CSAMR3CheckGates(PVM pVM, uint32_t iGate, uint32_t cGates);
+
+/**
+ * Record previous call instruction addresses
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param GCPtrCall Call address
+ */
+VMMR3DECL(int) CSAMR3RecordCallAddress(PVM pVM, RTRCPTR GCPtrCall);
+
+/** @} */
+#endif
+
+
+/** @} */
+RT_C_DECLS_END
+
+#endif
diff --git a/include/VBox/vmm/dbgf.h b/include/VBox/vmm/dbgf.h
new file mode 100644
index 00000000..65bb94c7
--- /dev/null
+++ b/include/VBox/vmm/dbgf.h
@@ -0,0 +1,1658 @@
+/** @file
+ * DBGF - Debugger Facility.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_dbgf_h
+#define ___VBox_vmm_dbgf_h
+
+#include <VBox/types.h>
+#include <VBox/log.h> /* LOG_ENABLED */
+#include <VBox/vmm/vmm.h>
+#include <VBox/vmm/dbgfsel.h>
+
+#include <iprt/stdarg.h>
+#include <iprt/dbg.h>
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup grp_dbgf The Debugger Facility API
+ * @{
+ */
+
+#if defined(IN_RC) || defined(IN_RING0)
+/** @addgroup grp_dbgf_rz The RZ DBGF API
+ * @ingroup grp_dbgf
+ * @{
+ */
+VMMRZDECL(int) DBGFRZTrap01Handler(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCUINTREG uDr6);
+VMMRZDECL(int) DBGFRZTrap03Handler(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame);
+/** @} */
+#endif
+
+
+
+#ifdef IN_RING3
+
+/**
+ * Mixed address.
+ */
+typedef struct DBGFADDRESS
+{
+ /** The flat address. */
+ RTGCUINTPTR FlatPtr;
+ /** The selector offset address. */
+ RTGCUINTPTR off;
+ /** The selector. DBGF_SEL_FLAT is a legal value. */
+ RTSEL Sel;
+ /** Flags describing further details about the address. */
+ uint16_t fFlags;
+} DBGFADDRESS;
+/** Pointer to a mixed address. */
+typedef DBGFADDRESS *PDBGFADDRESS;
+/** Pointer to a const mixed address. */
+typedef const DBGFADDRESS *PCDBGFADDRESS;
+
+/** @name DBGFADDRESS Flags.
+ * @{ */
+/** A 16:16 far address. */
+#define DBGFADDRESS_FLAGS_FAR16 0
+/** A 16:32 far address. */
+#define DBGFADDRESS_FLAGS_FAR32 1
+/** A 16:64 far address. */
+#define DBGFADDRESS_FLAGS_FAR64 2
+/** A flat address. */
+#define DBGFADDRESS_FLAGS_FLAT 3
+/** A physical address. */
+#define DBGFADDRESS_FLAGS_PHYS 4
+/** A physical address. */
+#define DBGFADDRESS_FLAGS_RING0 5
+/** The address type mask. */
+#define DBGFADDRESS_FLAGS_TYPE_MASK 7
+
+/** Set if the address is valid. */
+#define DBGFADDRESS_FLAGS_VALID RT_BIT(3)
+
+/** The address is within the hypervisor memoary area (HMA).
+ * If not set, the address can be assumed to be a guest address. */
+#define DBGFADDRESS_FLAGS_HMA RT_BIT(4)
+
+/** Checks if the mixed address is flat or not. */
+#define DBGFADDRESS_IS_FLAT(pAddress) ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_FLAT )
+/** Checks if the mixed address is flat or not. */
+#define DBGFADDRESS_IS_PHYS(pAddress) ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_PHYS )
+/** Checks if the mixed address is far 16:16 or not. */
+#define DBGFADDRESS_IS_FAR16(pAddress) ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_FAR16 )
+/** Checks if the mixed address is far 16:32 or not. */
+#define DBGFADDRESS_IS_FAR32(pAddress) ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_FAR32 )
+/** Checks if the mixed address is far 16:64 or not. */
+#define DBGFADDRESS_IS_FAR64(pAddress) ( ((pAddress)->fFlags & DBGFADDRESS_FLAGS_TYPE_MASK) == DBGFADDRESS_FLAGS_FAR64 )
+/** Checks if the mixed address is valid. */
+#define DBGFADDRESS_IS_VALID(pAddress) ( !!((pAddress)->fFlags & DBGFADDRESS_FLAGS_VALID) )
+/** Checks if the address is flagged as within the HMA. */
+#define DBGFADDRESS_IS_HMA(pAddress) ( !!((pAddress)->fFlags & DBGFADDRESS_FLAGS_HMA) )
+/** @} */
+
+VMMR3DECL(int) DBGFR3AddrFromSelOff(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, RTSEL Sel, RTUINTPTR off);
+VMMR3DECL(int) DBGFR3AddrFromSelInfoOff(PVM pVM, PDBGFADDRESS pAddress, PCDBGFSELINFO pSelInfo, RTUINTPTR off);
+VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromFlat(PVM pVM, PDBGFADDRESS pAddress, RTGCUINTPTR FlatPtr);
+VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromPhys(PVM pVM, PDBGFADDRESS pAddress, RTGCPHYS PhysAddr);
+VMMR3DECL(bool) DBGFR3AddrIsValid(PVM pVM, PCDBGFADDRESS pAddress);
+VMMR3DECL(int) DBGFR3AddrToPhys(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, PRTGCPHYS pGCPhys);
+VMMR3DECL(int) DBGFR3AddrToHostPhys(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, PRTHCPHYS pHCPhys);
+VMMR3DECL(int) DBGFR3AddrToVolatileR3Ptr(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, bool fReadOnly, void **ppvR3Ptr);
+VMMR3DECL(PDBGFADDRESS) DBGFR3AddrAdd(PDBGFADDRESS pAddress, RTGCUINTPTR uAddend);
+VMMR3DECL(PDBGFADDRESS) DBGFR3AddrSub(PDBGFADDRESS pAddress, RTGCUINTPTR uSubtrahend);
+
+#endif /* IN_RING3 */
+
+
+
+/**
+ * VMM Debug Event Type.
+ */
+typedef enum DBGFEVENTTYPE
+{
+ /** Halt completed.
+ * This notifies that a halt command have been successfully completed.
+ */
+ DBGFEVENT_HALT_DONE = 0,
+ /** Detach completed.
+ * This notifies that the detach command have been successfully completed.
+ */
+ DBGFEVENT_DETACH_DONE,
+ /** The command from the debugger is not recognized.
+ * This means internal error or half implemented features.
+ */
+ DBGFEVENT_INVALID_COMMAND,
+
+
+ /** Fatal error.
+ * This notifies a fatal error in the VMM and that the debugger get's a
+ * chance to first hand information about the the problem.
+ */
+ DBGFEVENT_FATAL_ERROR = 100,
+ /** Breakpoint Hit.
+ * This notifies that a breakpoint installed by the debugger was hit. The
+ * identifier of the breakpoint can be found in the DBGFEVENT::u::Bp::iBp member.
+ */
+ DBGFEVENT_BREAKPOINT,
+ /** Breakpoint Hit in the Hypervisor.
+ * This notifies that a breakpoint installed by the debugger was hit. The
+ * identifier of the breakpoint can be found in the DBGFEVENT::u::Bp::iBp member.
+ */
+ DBGFEVENT_BREAKPOINT_HYPER,
+ /** Assertion in the Hypervisor (breakpoint instruction).
+ * This notifies that a breakpoint instruction was hit in the hypervisor context.
+ */
+ DBGFEVENT_ASSERTION_HYPER,
+ /** Single Stepped.
+ * This notifies that a single step operation was completed.
+ */
+ DBGFEVENT_STEPPED,
+ /** Single Stepped.
+ * This notifies that a hypervisor single step operation was completed.
+ */
+ DBGFEVENT_STEPPED_HYPER,
+ /** The developer have used the DBGFSTOP macro or the PDMDeviceDBGFSTOP function
+ * to bring up the debugger at a specific place.
+ */
+ DBGFEVENT_DEV_STOP,
+ /** The VM is terminating.
+ * When this notification is received, the debugger thread should detach ASAP.
+ */
+ DBGFEVENT_TERMINATING,
+
+ /** The usual 32-bit hack. */
+ DBGFEVENT_32BIT_HACK = 0x7fffffff
+} DBGFEVENTTYPE;
+
+
+/**
+ * The context of an event.
+ */
+typedef enum DBGFEVENTCTX
+{
+ /** The usual invalid entry. */
+ DBGFEVENTCTX_INVALID = 0,
+ /** Raw mode. */
+ DBGFEVENTCTX_RAW,
+ /** Recompiled mode. */
+ DBGFEVENTCTX_REM,
+ /** VMX / AVT mode. */
+ DBGFEVENTCTX_HWACCL,
+ /** Hypervisor context. */
+ DBGFEVENTCTX_HYPER,
+ /** Other mode */
+ DBGFEVENTCTX_OTHER,
+
+ /** The usual 32-bit hack */
+ DBGFEVENTCTX_32BIT_HACK = 0x7fffffff
+} DBGFEVENTCTX;
+
+/**
+ * VMM Debug Event.
+ */
+typedef struct DBGFEVENT
+{
+ /** Type. */
+ DBGFEVENTTYPE enmType;
+ /** Context */
+ DBGFEVENTCTX enmCtx;
+ /** Type specific data. */
+ union
+ {
+ /** Fatal error details. */
+ struct
+ {
+ /** The GC return code. */
+ int rc;
+ } FatalError;
+
+ /** Source location. */
+ struct
+ {
+ /** File name. */
+ R3PTRTYPE(const char *) pszFile;
+ /** Function name. */
+ R3PTRTYPE(const char *) pszFunction;
+ /** Message. */
+ R3PTRTYPE(const char *) pszMessage;
+ /** Line number. */
+ unsigned uLine;
+ } Src;
+
+ /** Assertion messages. */
+ struct
+ {
+ /** The first message. */
+ R3PTRTYPE(const char *) pszMsg1;
+ /** The second message. */
+ R3PTRTYPE(const char *) pszMsg2;
+ } Assert;
+
+ /** Breakpoint. */
+ struct DBGFEVENTBP
+ {
+ /** The identifier of the breakpoint which was hit. */
+ RTUINT iBp;
+ } Bp;
+ /** Padding for ensuring that the structure is 8 byte aligned. */
+ uint64_t au64Padding[4];
+ } u;
+} DBGFEVENT;
+/** Pointer to VMM Debug Event. */
+typedef DBGFEVENT *PDBGFEVENT;
+/** Pointer to const VMM Debug Event. */
+typedef const DBGFEVENT *PCDBGFEVENT;
+
+#ifdef IN_RING3 /* The event API only works in ring-3. */
+
+/** @def DBGFSTOP
+ * Stops the debugger raising a DBGFEVENT_DEVELOPER_STOP event.
+ *
+ * @returns VBox status code which must be propagated up to EM if not VINF_SUCCESS.
+ * @param pVM VM Handle.
+ */
+# ifdef VBOX_STRICT
+# define DBGFSTOP(pVM) DBGFR3EventSrc(pVM, DBGFEVENT_DEV_STOP, __FILE__, __LINE__, __PRETTY_FUNCTION__, NULL)
+# else
+# define DBGFSTOP(pVM) VINF_SUCCESS
+# endif
+
+VMMR3DECL(int) DBGFR3Init(PVM pVM);
+VMMR3DECL(int) DBGFR3Term(PVM pVM);
+VMMR3DECL(void) DBGFR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3DECL(int) DBGFR3VMMForcedAction(PVM pVM);
+VMMR3DECL(int) DBGFR3Event(PVM pVM, DBGFEVENTTYPE enmEvent);
+VMMR3DECL(int) DBGFR3EventSrc(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine, const char *pszFunction, const char *pszFormat, ...);
+VMMR3DECL(int) DBGFR3EventSrcV(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszFile, unsigned uLine, const char *pszFunction, const char *pszFormat, va_list args);
+VMMR3DECL(int) DBGFR3EventAssertion(PVM pVM, DBGFEVENTTYPE enmEvent, const char *pszMsg1, const char *pszMsg2);
+VMMR3DECL(int) DBGFR3EventBreakpoint(PVM pVM, DBGFEVENTTYPE enmEvent);
+VMMR3DECL(int) DBGFR3Attach(PVM pVM);
+VMMR3DECL(int) DBGFR3Detach(PVM pVM);
+VMMR3DECL(int) DBGFR3EventWait(PVM pVM, RTMSINTERVAL cMillies, PCDBGFEVENT *ppEvent);
+VMMR3DECL(int) DBGFR3Halt(PVM pVM);
+VMMR3DECL(bool) DBGFR3IsHalted(PVM pVM);
+VMMR3DECL(bool) DBGFR3CanWait(PVM pVM);
+VMMR3DECL(int) DBGFR3Resume(PVM pVM);
+VMMR3DECL(int) DBGFR3Step(PVM pVM, VMCPUID idCpu);
+VMMR3DECL(int) DBGFR3PrgStep(PVMCPU pVCpu);
+
+#endif /* IN_RING3 */
+
+
+
+/** Breakpoint type. */
+typedef enum DBGFBPTYPE
+{
+ /** Free breakpoint entry. */
+ DBGFBPTYPE_FREE = 0,
+ /** Debug register. */
+ DBGFBPTYPE_REG,
+ /** INT 3 instruction. */
+ DBGFBPTYPE_INT3,
+ /** Recompiler. */
+ DBGFBPTYPE_REM,
+ /** ensure 32-bit size. */
+ DBGFBPTYPE_32BIT_HACK = 0x7fffffff
+} DBGFBPTYPE;
+
+
+/**
+ * A Breakpoint.
+ */
+typedef struct DBGFBP
+{
+ /** The number of breakpoint hits. */
+ uint64_t cHits;
+ /** The hit number which starts to trigger the breakpoint. */
+ uint64_t iHitTrigger;
+ /** The hit number which stops triggering the breakpoint (disables it).
+ * Use ~(uint64_t)0 if it should never stop. */
+ uint64_t iHitDisable;
+ /** The Flat GC address of the breakpoint.
+ * (PC register value if REM type?) */
+ RTGCUINTPTR GCPtr;
+ /** The breakpoint id. */
+ uint32_t iBp;
+ /** The breakpoint status - enabled or disabled. */
+ bool fEnabled;
+
+ /** The breakpoint type. */
+ DBGFBPTYPE enmType;
+
+#if GC_ARCH_BITS == 64
+ uint32_t u32Padding;
+#endif
+
+ /** Union of type specific data. */
+ union
+ {
+ /** Debug register data. */
+ struct DBGFBPREG
+ {
+ /** The debug register number. */
+ uint8_t iReg;
+ /** The access type (one of the X86_DR7_RW_* value). */
+ uint8_t fType;
+ /** The access size. */
+ uint8_t cb;
+ } Reg;
+ /** Recompiler breakpoint data. */
+ struct DBGFBPINT3
+ {
+ /** The byte value we replaced by the INT 3 instruction. */
+ uint8_t bOrg;
+ } Int3;
+
+ /** Recompiler breakpoint data. */
+ struct DBGFBPREM
+ {
+ /** nothing yet */
+ uint8_t fDummy;
+ } Rem;
+ /** Paddind to ensure that the size is identical on win32 and linux. */
+ uint64_t u64Padding;
+ } u;
+} DBGFBP;
+
+/** Pointer to a breakpoint. */
+typedef DBGFBP *PDBGFBP;
+/** Pointer to a const breakpoint. */
+typedef const DBGFBP *PCDBGFBP;
+
+#ifdef IN_RING3 /* The breakpoint management API is only available in ring-3. */
+VMMR3DECL(int) DBGFR3BpSet(PVM pVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp);
+VMMR3DECL(int) DBGFR3BpSetReg(PVM pVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable,
+ uint8_t fType, uint8_t cb, uint32_t *piBp);
+VMMR3DECL(int) DBGFR3BpSetREM(PVM pVM, PCDBGFADDRESS pAddress, uint64_t iHitTrigger, uint64_t iHitDisable, uint32_t *piBp);
+VMMR3DECL(int) DBGFR3BpClear(PVM pVM, uint32_t iBp);
+VMMR3DECL(int) DBGFR3BpEnable(PVM pVM, uint32_t iBp);
+VMMR3DECL(int) DBGFR3BpDisable(PVM pVM, uint32_t iBp);
+
+/**
+ * Breakpoint enumeration callback function.
+ *
+ * @returns VBox status code. Any failure will stop the enumeration.
+ * @param pVM The VM handle.
+ * @param pvUser The user argument.
+ * @param pBp Pointer to the breakpoint information. (readonly)
+ */
+typedef DECLCALLBACK(int) FNDBGFBPENUM(PVM pVM, void *pvUser, PCDBGFBP pBp);
+/** Pointer to a breakpoint enumeration callback function. */
+typedef FNDBGFBPENUM *PFNDBGFBPENUM;
+
+VMMR3DECL(int) DBGFR3BpEnum(PVM pVM, PFNDBGFBPENUM pfnCallback, void *pvUser);
+#endif /* IN_RING3 */
+
+VMMDECL(RTGCUINTREG) DBGFBpGetDR7(PVM pVM);
+VMMDECL(RTGCUINTREG) DBGFBpGetDR0(PVM pVM);
+VMMDECL(RTGCUINTREG) DBGFBpGetDR1(PVM pVM);
+VMMDECL(RTGCUINTREG) DBGFBpGetDR2(PVM pVM);
+VMMDECL(RTGCUINTREG) DBGFBpGetDR3(PVM pVM);
+VMMDECL(bool) DBGFIsStepping(PVMCPU pVCpu);
+
+
+#ifdef IN_RING3 /* The CPU mode API only works in ring-3. */
+VMMR3DECL(CPUMMODE) DBGFR3CpuGetMode(PVM pVM, VMCPUID idCpu);
+#endif
+
+
+
+#ifdef IN_RING3 /* The info callbacks API only works in ring-3. */
+
+/**
+ * Info helper callback structure.
+ */
+typedef struct DBGFINFOHLP
+{
+ /**
+ * Print formatted string.
+ *
+ * @param pHlp Pointer to this structure.
+ * @param pszFormat The format string.
+ * @param ... Arguments.
+ */
+ DECLCALLBACKMEMBER(void, pfnPrintf)(PCDBGFINFOHLP pHlp, const char *pszFormat, ...);
+
+ /**
+ * Print formatted string.
+ *
+ * @param pHlp Pointer to this structure.
+ * @param pszFormat The format string.
+ * @param args Argument list.
+ */
+ DECLCALLBACKMEMBER(void, pfnPrintfV)(PCDBGFINFOHLP pHlp, const char *pszFormat, va_list args);
+} DBGFINFOHLP;
+
+
+/**
+ * Info handler, device version.
+ *
+ * @param pDevIns The device instance which registered the info.
+ * @param pHlp Callback functions for doing output.
+ * @param pszArgs Argument string. Optional and specific to the handler.
+ */
+typedef DECLCALLBACK(void) FNDBGFHANDLERDEV(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs);
+/** Pointer to a FNDBGFHANDLERDEV function. */
+typedef FNDBGFHANDLERDEV *PFNDBGFHANDLERDEV;
+
+/**
+ * Info handler, USB device version.
+ *
+ * @param pUsbIns The USB device instance which registered the info.
+ * @param pHlp Callback functions for doing output.
+ * @param pszArgs Argument string. Optional and specific to the handler.
+ */
+typedef DECLCALLBACK(void) FNDBGFHANDLERUSB(PPDMUSBINS pUsbIns, PCDBGFINFOHLP pHlp, const char *pszArgs);
+/** Pointer to a FNDBGFHANDLERUSB function. */
+typedef FNDBGFHANDLERUSB *PFNDBGFHANDLERUSB;
+
+/**
+ * Info handler, driver version.
+ *
+ * @param pDrvIns The driver instance which registered the info.
+ * @param pHlp Callback functions for doing output.
+ * @param pszArgs Argument string. Optional and specific to the handler.
+ */
+typedef DECLCALLBACK(void) FNDBGFHANDLERDRV(PPDMDRVINS pDrvIns, PCDBGFINFOHLP pHlp, const char *pszArgs);
+/** Pointer to a FNDBGFHANDLERDRV function. */
+typedef FNDBGFHANDLERDRV *PFNDBGFHANDLERDRV;
+
+/**
+ * Info handler, internal version.
+ *
+ * @param pVM The VM handle.
+ * @param pHlp Callback functions for doing output.
+ * @param pszArgs Argument string. Optional and specific to the handler.
+ */
+typedef DECLCALLBACK(void) FNDBGFHANDLERINT(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
+/** Pointer to a FNDBGFHANDLERINT function. */
+typedef FNDBGFHANDLERINT *PFNDBGFHANDLERINT;
+
+/**
+ * Info handler, external version.
+ *
+ * @param pvUser User argument.
+ * @param pHlp Callback functions for doing output.
+ * @param pszArgs Argument string. Optional and specific to the handler.
+ */
+typedef DECLCALLBACK(void) FNDBGFHANDLEREXT(void *pvUser, PCDBGFINFOHLP pHlp, const char *pszArgs);
+/** Pointer to a FNDBGFHANDLEREXT function. */
+typedef FNDBGFHANDLEREXT *PFNDBGFHANDLEREXT;
+
+
+/** @name Flags for the info registration functions.
+ * @{ */
+/** The handler must run on the EMT. */
+#define DBGFINFO_FLAGS_RUN_ON_EMT RT_BIT(0)
+/** @} */
+
+VMMR3DECL(int) DBGFR3InfoRegisterDevice(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler, PPDMDEVINS pDevIns);
+VMMR3DECL(int) DBGFR3InfoRegisterDriver(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDRV pfnHandler, PPDMDRVINS pDrvIns);
+VMMR3DECL(int) DBGFR3InfoRegisterInternal(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERINT pfnHandler);
+VMMR3DECL(int) DBGFR3InfoRegisterInternalEx(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLERINT pfnHandler, uint32_t fFlags);
+VMMR3DECL(int) DBGFR3InfoRegisterExternal(PVM pVM, const char *pszName, const char *pszDesc, PFNDBGFHANDLEREXT pfnHandler, void *pvUser);
+VMMR3DECL(int) DBGFR3InfoDeregisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName);
+VMMR3DECL(int) DBGFR3InfoDeregisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName);
+VMMR3DECL(int) DBGFR3InfoDeregisterInternal(PVM pVM, const char *pszName);
+VMMR3DECL(int) DBGFR3InfoDeregisterExternal(PVM pVM, const char *pszName);
+VMMR3DECL(int) DBGFR3Info(PVM pVM, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp);
+VMMR3DECL(int) DBGFR3InfoEx(PVM pVM, VMCPUID idCpu, const char *pszName, const char *pszArgs, PCDBGFINFOHLP pHlp);
+VMMR3DECL(int) DBGFR3InfoLogRel(PVM pVM, const char *pszName, const char *pszArgs);
+VMMR3DECL(int) DBGFR3InfoStdErr(PVM pVM, const char *pszName, const char *pszArgs);
+VMMR3DECL(int) DBGFR3InfoMulti(PVM pVM, const char *pszIncludePat, const char *pszExcludePat,
+ const char *pszSepFmt, PCDBGFINFOHLP pHlp);
+
+/** @def DBGFR3InfoLog
+ * Display a piece of info writing to the log if enabled.
+ *
+ * @param pVM VM handle.
+ * @param pszName The identifier of the info to display.
+ * @param pszArgs Arguments to the info handler.
+ */
+#ifdef LOG_ENABLED
+#define DBGFR3InfoLog(pVM, pszName, pszArgs) \
+ do { \
+ if (LogIsEnabled()) \
+ DBGFR3Info(pVM, pszName, pszArgs, NULL); \
+ } while (0)
+#else
+#define DBGFR3InfoLog(pVM, pszName, pszArgs) do { } while (0)
+#endif
+
+/**
+ * Enumeration callback for use with DBGFR3InfoEnum.
+ *
+ * @returns VBox status code.
+ * A status code indicating failure will end the enumeration
+ * and DBGFR3InfoEnum will return with that status code.
+ * @param pVM VM handle.
+ * @param pszName Info identifier name.
+ * @param pszDesc The description.
+ */
+typedef DECLCALLBACK(int) FNDBGFINFOENUM(PVM pVM, const char *pszName, const char *pszDesc, void *pvUser);
+/** Pointer to a FNDBGFINFOENUM function. */
+typedef FNDBGFINFOENUM *PFNDBGFINFOENUM;
+
+VMMR3DECL(int) DBGFR3InfoEnum(PVM pVM, PFNDBGFINFOENUM pfnCallback, void *pvUser);
+VMMR3DECL(PCDBGFINFOHLP) DBGFR3InfoLogHlp(void);
+VMMR3DECL(PCDBGFINFOHLP) DBGFR3InfoLogRelHlp(void);
+
+#endif /* IN_RING3 */
+
+
+#ifdef IN_RING3 /* The log contrl API only works in ring-3. */
+VMMR3DECL(int) DBGFR3LogModifyGroups(PVM pVM, const char *pszGroupSettings);
+VMMR3DECL(int) DBGFR3LogModifyFlags(PVM pVM, const char *pszFlagSettings);
+VMMR3DECL(int) DBGFR3LogModifyDestinations(PVM pVM, const char *pszDestSettings);
+#endif /* IN_RING3 */
+
+#ifdef IN_RING3 /* The debug information management APIs only works in ring-3. */
+
+/** Max length (including '\\0') of a symbol name. */
+#define DBGF_SYMBOL_NAME_LENGTH 512
+
+/**
+ * Debug symbol.
+ */
+typedef struct DBGFSYMBOL
+{
+ /** Symbol value (address). */
+ RTGCUINTPTR Value;
+ /** Symbol size. */
+ uint32_t cb;
+ /** Symbol Flags. (reserved). */
+ uint32_t fFlags;
+ /** Symbol name. */
+ char szName[DBGF_SYMBOL_NAME_LENGTH];
+} DBGFSYMBOL;
+/** Pointer to debug symbol. */
+typedef DBGFSYMBOL *PDBGFSYMBOL;
+/** Pointer to const debug symbol. */
+typedef const DBGFSYMBOL *PCDBGFSYMBOL;
+
+/**
+ * Debug line number information.
+ */
+typedef struct DBGFLINE
+{
+ /** Address. */
+ RTGCUINTPTR Address;
+ /** Line number. */
+ uint32_t uLineNo;
+ /** Filename. */
+ char szFilename[260];
+} DBGFLINE;
+/** Pointer to debug line number. */
+typedef DBGFLINE *PDBGFLINE;
+/** Pointer to const debug line number. */
+typedef const DBGFLINE *PCDBGFLINE;
+
+/** @name Address spaces aliases.
+ * @{ */
+/** The guest global address space. */
+#define DBGF_AS_GLOBAL ((RTDBGAS)-1)
+/** The guest kernel address space.
+ * This is usually resolves to the same as DBGF_AS_GLOBAL. */
+#define DBGF_AS_KERNEL ((RTDBGAS)-2)
+/** The physical address space. */
+#define DBGF_AS_PHYS ((RTDBGAS)-3)
+/** Raw-mode context. */
+#define DBGF_AS_RC ((RTDBGAS)-4)
+/** Ring-0 context. */
+#define DBGF_AS_R0 ((RTDBGAS)-5)
+/** Raw-mode context and then global guest context.
+ * When used for looking up information, it works as if the call was first made
+ * with DBGF_AS_RC and then on failure with DBGF_AS_GLOBAL. When called for
+ * making address space changes, it works as if DBGF_AS_RC was used. */
+#define DBGF_AS_RC_AND_GC_GLOBAL ((RTDBGAS)-6)
+
+/** The first special one. */
+#define DBGF_AS_FIRST DBGF_AS_RC_AND_GC_GLOBAL
+/** The last special one. */
+#define DBGF_AS_LAST DBGF_AS_GLOBAL
+#endif
+/** The number of special address space handles. */
+#define DBGF_AS_COUNT (6U)
+#ifdef IN_RING3
+/** Converts an alias handle to an array index. */
+#define DBGF_AS_ALIAS_2_INDEX(hAlias) \
+ ( (uintptr_t)(hAlias) - (uintptr_t)DBGF_AS_FIRST )
+/** Predicat macro that check if the specified handle is an alias. */
+#define DBGF_AS_IS_ALIAS(hAlias) \
+ ( DBGF_AS_ALIAS_2_INDEX(hAlias) < DBGF_AS_COUNT )
+/** Predicat macro that check if the specified alias is a fixed one or not. */
+#define DBGF_AS_IS_FIXED_ALIAS(hAlias) \
+ ( DBGF_AS_ALIAS_2_INDEX(hAlias) < (uintptr_t)DBGF_AS_PHYS - (uintptr_t)DBGF_AS_FIRST + 1U )
+
+/** @} */
+
+VMMR3DECL(int) DBGFR3AsAdd(PVM pVM, RTDBGAS hDbgAs, RTPROCESS ProcId);
+VMMR3DECL(int) DBGFR3AsDelete(PVM pVM, RTDBGAS hDbgAs);
+VMMR3DECL(int) DBGFR3AsSetAlias(PVM pVM, RTDBGAS hAlias, RTDBGAS hAliasFor);
+VMMR3DECL(RTDBGAS) DBGFR3AsResolve(PVM pVM, RTDBGAS hAlias);
+VMMR3DECL(RTDBGAS) DBGFR3AsResolveAndRetain(PVM pVM, RTDBGAS hAlias);
+VMMR3DECL(RTDBGAS) DBGFR3AsQueryByName(PVM pVM, const char *pszName);
+VMMR3DECL(RTDBGAS) DBGFR3AsQueryByPid(PVM pVM, RTPROCESS ProcId);
+
+VMMR3DECL(int) DBGFR3AsLoadImage(PVM pVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags);
+VMMR3DECL(int) DBGFR3AsLoadMap(PVM pVM, RTDBGAS hDbgAs, const char *pszFilename, const char *pszModName, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, RTGCUINTPTR uSubtrahend, uint32_t fFlags);
+VMMR3DECL(int) DBGFR3AsLinkModule(PVM pVM, RTDBGAS hDbgAs, RTDBGMOD hMod, PCDBGFADDRESS pModAddress, RTDBGSEGIDX iModSeg, uint32_t fFlags);
+
+VMMR3DECL(int) DBGFR3AsSymbolByAddr(PVM pVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, PRTGCINTPTR poffDisp, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod);
+VMMR3DECL(PRTDBGSYMBOL) DBGFR3AsSymbolByAddrA(PVM pVM, RTDBGAS hDbgAs, PCDBGFADDRESS pAddress, PRTGCINTPTR poffDisp, PRTDBGMOD phMod);
+VMMR3DECL(int) DBGFR3AsSymbolByName(PVM pVM, RTDBGAS hDbgAs, const char *pszSymbol, PRTDBGSYMBOL pSymbol, PRTDBGMOD phMod);
+
+/* The following are soon to be obsoleted: */
+VMMR3DECL(int) DBGFR3ModuleLoad(PVM pVM, const char *pszFilename, RTGCUINTPTR AddressDelta, const char *pszName, RTGCUINTPTR ModuleAddress, unsigned cbImage);
+VMMR3DECL(void) DBGFR3ModuleRelocate(PVM pVM, RTGCUINTPTR OldImageBase, RTGCUINTPTR NewImageBase, RTGCUINTPTR cbImage,
+ const char *pszFilename, const char *pszName);
+VMMR3DECL(int) DBGFR3SymbolAdd(PVM pVM, RTGCUINTPTR ModuleAddress, RTGCUINTPTR SymbolAddress, RTUINT cbSymbol, const char *pszSymbol);
+VMMR3DECL(int) DBGFR3SymbolByAddr(PVM pVM, RTGCUINTPTR Address, PRTGCINTPTR poffDisplacement, PDBGFSYMBOL pSymbol);
+VMMR3DECL(int) DBGFR3SymbolByName(PVM pVM, const char *pszSymbol, PDBGFSYMBOL pSymbol);
+
+VMMR3DECL(int) DBGFR3LineByAddr(PVM pVM, RTGCUINTPTR Address, PRTGCINTPTR poffDisplacement, PDBGFLINE pLine);
+VMMR3DECL(PDBGFLINE) DBGFR3LineByAddrAlloc(PVM pVM, RTGCUINTPTR Address, PRTGCINTPTR poffDisplacement);
+VMMR3DECL(void) DBGFR3LineFree(PDBGFLINE pLine);
+
+#endif /* IN_RING3 */
+
+#ifdef IN_RING3 /* The stack API only works in ring-3. */
+
+/**
+ * Return type.
+ */
+typedef enum DBGFRETRUNTYPE
+{
+ /** The usual invalid 0 value. */
+ DBGFRETURNTYPE_INVALID = 0,
+ /** Near 16-bit return. */
+ DBGFRETURNTYPE_NEAR16,
+ /** Near 32-bit return. */
+ DBGFRETURNTYPE_NEAR32,
+ /** Near 64-bit return. */
+ DBGFRETURNTYPE_NEAR64,
+ /** Far 16:16 return. */
+ DBGFRETURNTYPE_FAR16,
+ /** Far 16:32 return. */
+ DBGFRETURNTYPE_FAR32,
+ /** Far 16:64 return. */
+ DBGFRETURNTYPE_FAR64,
+ /** 16-bit iret return (e.g. real or 286 protect mode). */
+ DBGFRETURNTYPE_IRET16,
+ /** 32-bit iret return. */
+ DBGFRETURNTYPE_IRET32,
+ /** 32-bit iret return. */
+ DBGFRETURNTYPE_IRET32_PRIV,
+ /** 32-bit iret return to V86 mode. */
+ DBGFRETURNTYPE_IRET32_V86,
+ /** @todo 64-bit iret return. */
+ DBGFRETURNTYPE_IRET64,
+ /** The end of the valid return types. */
+ DBGFRETURNTYPE_END,
+ /** The usual 32-bit blowup. */
+ DBGFRETURNTYPE_32BIT_HACK = 0x7fffffff
+} DBGFRETURNTYPE;
+
+/**
+ * Figures the size of the return state on the stack.
+ *
+ * @returns number of bytes. 0 if invalid parameter.
+ * @param enmRetType The type of return.
+ */
+DECLINLINE(unsigned) DBGFReturnTypeSize(DBGFRETURNTYPE enmRetType)
+{
+ switch (enmRetType)
+ {
+ case DBGFRETURNTYPE_NEAR16: return 2;
+ case DBGFRETURNTYPE_NEAR32: return 4;
+ case DBGFRETURNTYPE_NEAR64: return 8;
+ case DBGFRETURNTYPE_FAR16: return 4;
+ case DBGFRETURNTYPE_FAR32: return 4;
+ case DBGFRETURNTYPE_FAR64: return 8;
+ case DBGFRETURNTYPE_IRET16: return 6;
+ case DBGFRETURNTYPE_IRET32: return 4*3;
+ case DBGFRETURNTYPE_IRET32_PRIV: return 4*5;
+ case DBGFRETURNTYPE_IRET32_V86: return 4*9;
+ case DBGFRETURNTYPE_IRET64:
+ default:
+ return 0;
+ }
+}
+
+
+/** Pointer to stack frame info. */
+typedef struct DBGFSTACKFRAME *PDBGFSTACKFRAME;
+/** Pointer to const stack frame info. */
+typedef struct DBGFSTACKFRAME const *PCDBGFSTACKFRAME;
+/**
+ * Info about a stack frame.
+ */
+typedef struct DBGFSTACKFRAME
+{
+ /** Frame number. */
+ uint32_t iFrame;
+ /** Frame flags. */
+ uint32_t fFlags;
+ /** The frame address.
+ * The off member is [e|r]bp and the Sel member is ss. */
+ DBGFADDRESS AddrFrame;
+ /** The stack address of the frame.
+ * The off member is [e|r]sp and the Sel member is ss. */
+ DBGFADDRESS AddrStack;
+ /** The program counter (PC) address of the frame.
+ * The off member is [e|r]ip and the Sel member is cs. */
+ DBGFADDRESS AddrPC;
+ /** Pointer to the symbol nearest the program counter (PC). NULL if not found. */
+ PRTDBGSYMBOL pSymPC;
+ /** Pointer to the linnumber nearest the program counter (PC). NULL if not found. */
+ PDBGFLINE pLinePC;
+
+ /** The return frame address.
+ * The off member is [e|r]bp and the Sel member is ss. */
+ DBGFADDRESS AddrReturnFrame;
+ /** The return stack address.
+ * The off member is [e|r]sp and the Sel member is ss. */
+ DBGFADDRESS AddrReturnStack;
+ /** The way this frame returns to the next one. */
+ DBGFRETURNTYPE enmReturnType;
+
+ /** The program counter (PC) address which the frame returns to.
+ * The off member is [e|r]ip and the Sel member is cs. */
+ DBGFADDRESS AddrReturnPC;
+ /** Pointer to the symbol nearest the return PC. NULL if not found. */
+ PRTDBGSYMBOL pSymReturnPC;
+ /** Pointer to the linnumber nearest the return PC. NULL if not found. */
+ PDBGFLINE pLineReturnPC;
+
+ /** 32-bytes of stack arguments. */
+ union
+ {
+ /** 64-bit view */
+ uint64_t au64[4];
+ /** 32-bit view */
+ uint32_t au32[8];
+ /** 16-bit view */
+ uint16_t au16[16];
+ /** 8-bit view */
+ uint8_t au8[32];
+ } Args;
+
+ /** Pointer to the next frame.
+ * Might not be used in some cases, so consider it internal. */
+ PCDBGFSTACKFRAME pNextInternal;
+ /** Pointer to the first frame.
+ * Might not be used in some cases, so consider it internal. */
+ PCDBGFSTACKFRAME pFirstInternal;
+} DBGFSTACKFRAME;
+
+/** @name DBGFSTACKFRAME Flags.
+ * @{ */
+/** Set if the content of the frame is filled in by DBGFR3StackWalk() and can be used
+ * to construct the next frame. */
+# define DBGFSTACKFRAME_FLAGS_ALL_VALID RT_BIT(0)
+/** This is the last stack frame we can read.
+ * This flag is not set if the walk stop because of max dept or recursion. */
+# define DBGFSTACKFRAME_FLAGS_LAST RT_BIT(1)
+/** This is the last record because we detected a loop. */
+# define DBGFSTACKFRAME_FLAGS_LOOP RT_BIT(2)
+/** This is the last record because we reached the maximum depth. */
+# define DBGFSTACKFRAME_FLAGS_MAX_DEPTH RT_BIT(3)
+/** 16-bit frame. */
+# define DBGFSTACKFRAME_FLAGS_16BIT RT_BIT(4)
+/** 32-bit frame. */
+# define DBGFSTACKFRAME_FLAGS_32BIT RT_BIT(5)
+/** 64-bit frame. */
+# define DBGFSTACKFRAME_FLAGS_64BIT RT_BIT(6)
+/** @} */
+
+/** @name DBGFCODETYPE
+ * @{ */
+typedef enum DBGFCODETYPE
+{
+ /** The usual invalid 0 value. */
+ DBGFCODETYPE_INVALID = 0,
+ /** Stack walk for guest code. */
+ DBGFCODETYPE_GUEST,
+ /** Stack walk for hypervisor code. */
+ DBGFCODETYPE_HYPER,
+ /** Stack walk for ring 0 code. */
+ DBGFCODETYPE_RING0,
+ /** The usual 32-bit blowup. */
+ DBGFCODETYPE_32BIT_HACK = 0x7fffffff
+} DBGFCODETYPE;
+/** @} */
+
+VMMR3DECL(int) DBGFR3StackWalkBegin(PVM pVM, VMCPUID idCpu, DBGFCODETYPE enmCodeType, PCDBGFSTACKFRAME *ppFirstFrame);
+VMMR3DECL(int) DBGFR3StackWalkBeginEx(PVM pVM, VMCPUID idCpu, DBGFCODETYPE enmCodeType, PCDBGFADDRESS pAddrFrame,
+ PCDBGFADDRESS pAddrStack,PCDBGFADDRESS pAddrPC,
+ DBGFRETURNTYPE enmReturnType, PCDBGFSTACKFRAME *ppFirstFrame);
+VMMR3DECL(PCDBGFSTACKFRAME) DBGFR3StackWalkNext(PCDBGFSTACKFRAME pCurrent);
+VMMR3DECL(void) DBGFR3StackWalkEnd(PCDBGFSTACKFRAME pFirstFrame);
+
+#endif /* IN_RING3 */
+
+
+#ifdef IN_RING3 /* The disassembly API only works in ring-3. */
+
+/** Flags to pass to DBGFR3DisasInstrEx().
+ * @{ */
+/** Disassemble the current guest instruction, with annotations. */
+#define DBGF_DISAS_FLAGS_CURRENT_GUEST RT_BIT(0)
+/** Disassemble the current hypervisor instruction, with annotations. */
+#define DBGF_DISAS_FLAGS_CURRENT_HYPER RT_BIT(1)
+/** No annotations for current context. */
+#define DBGF_DISAS_FLAGS_NO_ANNOTATION RT_BIT(2)
+/** No symbol lookup. */
+#define DBGF_DISAS_FLAGS_NO_SYMBOLS RT_BIT(3)
+/** No instruction bytes. */
+#define DBGF_DISAS_FLAGS_NO_BYTES RT_BIT(4)
+/** No address in the output. */
+#define DBGF_DISAS_FLAGS_NO_ADDRESS RT_BIT(5)
+/** Disassemble in the default mode of the specific context. */
+#define DBGF_DISAS_FLAGS_DEFAULT_MODE UINT32_C(0x00000000)
+/** Disassemble in 16-bit mode. */
+#define DBGF_DISAS_FLAGS_16BIT_MODE UINT32_C(0x10000000)
+/** Disassemble in 16-bit mode with real mode address translation. */
+#define DBGF_DISAS_FLAGS_16BIT_REAL_MODE UINT32_C(0x20000000)
+/** Disassemble in 32-bit mode. */
+#define DBGF_DISAS_FLAGS_32BIT_MODE UINT32_C(0x30000000)
+/** Disassemble in 64-bit mode. */
+#define DBGF_DISAS_FLAGS_64BIT_MODE UINT32_C(0x40000000)
+/** The disassembly mode mask. */
+#define DBGF_DISAS_FLAGS_MODE_MASK UINT32_C(0x70000000)
+/** Mask containing the valid flags. */
+#define DBGF_DISAS_FLAGS_VALID_MASK UINT32_C(0x7000007f)
+/** @} */
+
+/** Special flat selector. */
+#define DBGF_SEL_FLAT 1
+
+VMMR3DECL(int) DBGFR3DisasInstrEx(PVM pVM, VMCPUID idCpu, RTSEL Sel, RTGCPTR GCPtr, uint32_t fFlags,
+ char *pszOutput, uint32_t cbOutput, uint32_t *pcbInstr);
+VMMR3DECL(int) DBGFR3DisasInstrCurrent(PVMCPU pVCpu, char *pszOutput, uint32_t cbOutput);
+VMMR3DECL(int) DBGFR3DisasInstrCurrentLogInternal(PVMCPU pVCpu, const char *pszPrefix);
+
+/** @def DBGFR3DisasInstrCurrentLog
+ * Disassembles the current guest context instruction and writes it to the log.
+ * All registers and data will be displayed. Addresses will be attempted resolved to symbols.
+ */
+#ifdef LOG_ENABLED
+# define DBGFR3DisasInstrCurrentLog(pVCpu, pszPrefix) \
+ do { \
+ if (LogIsEnabled()) \
+ DBGFR3DisasInstrCurrentLogInternal(pVCpu, pszPrefix); \
+ } while (0)
+#else
+# define DBGFR3DisasInstrCurrentLog(pVCpu, pszPrefix) do { } while (0)
+#endif
+
+VMMR3DECL(int) DBGFR3DisasInstrLogInternal(PVMCPU pVCpu, RTSEL Sel, RTGCPTR GCPtr, const char *pszPrefix);
+
+/** @def DBGFR3DisasInstrLog
+ * Disassembles the specified guest context instruction and writes it to the log.
+ * Addresses will be attempted resolved to symbols.
+ * @thread Any EMT.
+ */
+# ifdef LOG_ENABLED
+# define DBGFR3DisasInstrLog(pVCpu, Sel, GCPtr, pszPrefix) \
+ do { \
+ if (LogIsEnabled()) \
+ DBGFR3DisasInstrLogInternal(pVCpu, Sel, GCPtr, pszPrefix); \
+ } while (0)
+# else
+# define DBGFR3DisasInstrLog(pVCpu, Sel, GCPtr, pszPrefix) do { } while (0)
+# endif
+#endif
+
+
+#ifdef IN_RING3
+VMMR3DECL(int) DBGFR3MemScan(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, RTGCUINTPTR cbRange, RTGCUINTPTR uAlign,
+ const void *pvNeedle, size_t cbNeedle, PDBGFADDRESS pHitAddress);
+VMMR3DECL(int) DBGFR3MemRead(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void *pvBuf, size_t cbRead);
+VMMR3DECL(int) DBGFR3MemReadString(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, char *pszBuf, size_t cbBuf);
+VMMR3DECL(int) DBGFR3MemWrite(PVM pVM, VMCPUID idCpu, PCDBGFADDRESS pAddress, void const *pvBuf, size_t cbRead);
+#endif
+
+
+/** @name Flags for DBGFR3PagingDumpEx, PGMR3DumpHierarchyHCEx and
+ * PGMR3DumpHierarchyGCEx
+ * @{ */
+/** The CR3 from the current CPU state. */
+#define DBGFPGDMP_FLAGS_CURRENT_CR3 RT_BIT_32(0)
+/** The current CPU paging mode (PSE, PAE, LM, EPT, NX). */
+#define DBGFPGDMP_FLAGS_CURRENT_MODE RT_BIT_32(1)
+/** Whether PSE is enabled (!DBGFPGDMP_FLAGS_CURRENT_STATE).
+ * Same value as X86_CR4_PSE. */
+#define DBGFPGDMP_FLAGS_PSE RT_BIT_32(4) /* */
+/** Whether PAE is enabled (!DBGFPGDMP_FLAGS_CURRENT_STATE).
+ * Same value as X86_CR4_PAE. */
+#define DBGFPGDMP_FLAGS_PAE RT_BIT_32(5) /* */
+/** Whether LME is enabled (!DBGFPGDMP_FLAGS_CURRENT_STATE).
+ * Same value as MSR_K6_EFER_LME. */
+#define DBGFPGDMP_FLAGS_LME RT_BIT_32(8)
+/** Whether nested paging is enabled (!DBGFPGDMP_FLAGS_CURRENT_STATE). */
+#define DBGFPGDMP_FLAGS_NP RT_BIT_32(9)
+/** Whether extended nested page tables are enabled
+ * (!DBGFPGDMP_FLAGS_CURRENT_STATE). */
+#define DBGFPGDMP_FLAGS_EPT RT_BIT_32(10)
+/** Whether no-execution is enabled (!DBGFPGDMP_FLAGS_CURRENT_STATE).
+ * Same value as MSR_K6_EFER_NXE. */
+#define DBGFPGDMP_FLAGS_NXE RT_BIT_32(11)
+/** Whether to print the CR3. */
+#define DBGFPGDMP_FLAGS_PRINT_CR3 RT_BIT_32(27)
+/** Whether to print the header. */
+#define DBGFPGDMP_FLAGS_HEADER RT_BIT_32(28)
+/** Whether to dump additional page information. */
+#define DBGFPGDMP_FLAGS_PAGE_INFO RT_BIT_32(29)
+/** Dump the shadow tables if set.
+ * Cannot be used together with DBGFPGDMP_FLAGS_GUEST. */
+#define DBGFPGDMP_FLAGS_SHADOW RT_BIT_32(30)
+/** Dump the guest tables if set.
+ * Cannot be used together with DBGFPGDMP_FLAGS_SHADOW. */
+#define DBGFPGDMP_FLAGS_GUEST RT_BIT_32(31)
+/** Mask of valid bits. */
+#define DBGFPGDMP_FLAGS_VALID_MASK UINT32_C(0xf8000f33)
+/** The mask of bits controlling the paging mode. */
+#define DBGFPGDMP_FLAGS_MODE_MASK UINT32_C(0x00000f32)
+/** @} */
+VMMDECL(int) DBGFR3PagingDumpEx(PVM pVM, VMCPUID idCpu, uint32_t fFlags, uint64_t cr3, uint64_t u64FirstAddr,
+ uint64_t u64LastAddr, uint32_t cMaxDepth, PCDBGFINFOHLP pHlp);
+
+
+/** @name DBGFR3SelQueryInfo flags.
+ * @{ */
+/** Get the info from the guest descriptor table. */
+#define DBGFSELQI_FLAGS_DT_GUEST UINT32_C(0)
+/** Get the info from the shadow descriptor table.
+ * Only works in raw-mode. */
+#define DBGFSELQI_FLAGS_DT_SHADOW UINT32_C(1)
+/** If currently executing in in 64-bit mode, blow up data selectors. */
+#define DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE UINT32_C(2)
+/** @} */
+VMMR3DECL(int) DBGFR3SelQueryInfo(PVM pVM, VMCPUID idCpu, RTSEL Sel, uint32_t fFlags, PDBGFSELINFO pSelInfo);
+
+
+/**
+ * Register identifiers.
+ */
+typedef enum DBGFREG
+{
+ /* General purpose registers: */
+ DBGFREG_AL = 0,
+ DBGFREG_AX = DBGFREG_AL,
+ DBGFREG_EAX = DBGFREG_AL,
+ DBGFREG_RAX = DBGFREG_AL,
+
+ DBGFREG_CL,
+ DBGFREG_CX = DBGFREG_CL,
+ DBGFREG_ECX = DBGFREG_CL,
+ DBGFREG_RCX = DBGFREG_CL,
+
+ DBGFREG_DL,
+ DBGFREG_DX = DBGFREG_DL,
+ DBGFREG_EDX = DBGFREG_DL,
+ DBGFREG_RDX = DBGFREG_DL,
+
+ DBGFREG_BL,
+ DBGFREG_BX = DBGFREG_BL,
+ DBGFREG_EBX = DBGFREG_BL,
+ DBGFREG_RBX = DBGFREG_BL,
+
+ DBGFREG_SPL,
+ DBGFREG_SP = DBGFREG_SPL,
+ DBGFREG_ESP = DBGFREG_SPL,
+ DBGFREG_RSP = DBGFREG_SPL,
+
+ DBGFREG_BPL,
+ DBGFREG_BP = DBGFREG_BPL,
+ DBGFREG_EBP = DBGFREG_BPL,
+ DBGFREG_RBP = DBGFREG_BPL,
+
+ DBGFREG_SIL,
+ DBGFREG_SI = DBGFREG_SIL,
+ DBGFREG_ESI = DBGFREG_SIL,
+ DBGFREG_RSI = DBGFREG_SIL,
+
+ DBGFREG_DIL,
+ DBGFREG_DI = DBGFREG_DIL,
+ DBGFREG_EDI = DBGFREG_DIL,
+ DBGFREG_RDI = DBGFREG_DIL,
+
+ DBGFREG_R8,
+ DBGFREG_R8B = DBGFREG_R8,
+ DBGFREG_R8W = DBGFREG_R8,
+ DBGFREG_R8D = DBGFREG_R8,
+
+ DBGFREG_R9,
+ DBGFREG_R9B = DBGFREG_R9,
+ DBGFREG_R9W = DBGFREG_R9,
+ DBGFREG_R9D = DBGFREG_R9,
+
+ DBGFREG_R10,
+ DBGFREG_R10B = DBGFREG_R10,
+ DBGFREG_R10W = DBGFREG_R10,
+ DBGFREG_R10D = DBGFREG_R10,
+
+ DBGFREG_R11,
+ DBGFREG_R11B = DBGFREG_R11,
+ DBGFREG_R11W = DBGFREG_R11,
+ DBGFREG_R11D = DBGFREG_R11,
+
+ DBGFREG_R12,
+ DBGFREG_R12B = DBGFREG_R12,
+ DBGFREG_R12W = DBGFREG_R12,
+ DBGFREG_R12D = DBGFREG_R12,
+
+ DBGFREG_R13,
+ DBGFREG_R13B = DBGFREG_R13,
+ DBGFREG_R13W = DBGFREG_R13,
+ DBGFREG_R13D = DBGFREG_R13,
+
+ DBGFREG_R14,
+ DBGFREG_R14B = DBGFREG_R14,
+ DBGFREG_R14W = DBGFREG_R14,
+ DBGFREG_R14D = DBGFREG_R14,
+
+ DBGFREG_R15,
+ DBGFREG_R15B = DBGFREG_R15,
+ DBGFREG_R15W = DBGFREG_R15,
+ DBGFREG_R15D = DBGFREG_R15,
+
+ /* Segments and other special registers: */
+ DBGFREG_CS,
+ DBGFREG_CS_ATTR,
+ DBGFREG_CS_BASE,
+ DBGFREG_CS_LIMIT,
+
+ DBGFREG_DS,
+ DBGFREG_DS_ATTR,
+ DBGFREG_DS_BASE,
+ DBGFREG_DS_LIMIT,
+
+ DBGFREG_ES,
+ DBGFREG_ES_ATTR,
+ DBGFREG_ES_BASE,
+ DBGFREG_ES_LIMIT,
+
+ DBGFREG_FS,
+ DBGFREG_FS_ATTR,
+ DBGFREG_FS_BASE,
+ DBGFREG_FS_LIMIT,
+
+ DBGFREG_GS,
+ DBGFREG_GS_ATTR,
+ DBGFREG_GS_BASE,
+ DBGFREG_GS_LIMIT,
+
+ DBGFREG_SS,
+ DBGFREG_SS_ATTR,
+ DBGFREG_SS_BASE,
+ DBGFREG_SS_LIMIT,
+
+ DBGFREG_IP,
+ DBGFREG_EIP = DBGFREG_IP,
+ DBGFREG_RIP = DBGFREG_IP,
+
+ DBGFREG_FLAGS,
+ DBGFREG_EFLAGS = DBGFREG_FLAGS,
+ DBGFREG_RFLAGS = DBGFREG_FLAGS,
+
+ /* FPU: */
+ DBGFREG_FCW,
+ DBGFREG_FSW,
+ DBGFREG_FTW,
+ DBGFREG_FOP,
+ DBGFREG_FPUIP,
+ DBGFREG_FPUCS,
+ DBGFREG_FPUDP,
+ DBGFREG_FPUDS,
+ DBGFREG_MXCSR,
+ DBGFREG_MXCSR_MASK,
+
+ DBGFREG_ST0,
+ DBGFREG_ST1,
+ DBGFREG_ST2,
+ DBGFREG_ST3,
+ DBGFREG_ST4,
+ DBGFREG_ST5,
+ DBGFREG_ST6,
+ DBGFREG_ST7,
+
+ DBGFREG_MM0,
+ DBGFREG_MM1,
+ DBGFREG_MM2,
+ DBGFREG_MM3,
+ DBGFREG_MM4,
+ DBGFREG_MM5,
+ DBGFREG_MM6,
+ DBGFREG_MM7,
+
+ /* SSE: */
+ DBGFREG_XMM0,
+ DBGFREG_XMM1,
+ DBGFREG_XMM2,
+ DBGFREG_XMM3,
+ DBGFREG_XMM4,
+ DBGFREG_XMM5,
+ DBGFREG_XMM6,
+ DBGFREG_XMM7,
+ DBGFREG_XMM8,
+ DBGFREG_XMM9,
+ DBGFREG_XMM10,
+ DBGFREG_XMM11,
+ DBGFREG_XMM12,
+ DBGFREG_XMM13,
+ DBGFREG_XMM14,
+ DBGFREG_XMM15,
+ /** @todo add XMM aliases. */
+
+ /* System registers: */
+ DBGFREG_GDTR_BASE,
+ DBGFREG_GDTR_LIMIT,
+ DBGFREG_IDTR_BASE,
+ DBGFREG_IDTR_LIMIT,
+ DBGFREG_LDTR,
+ DBGFREG_LDTR_ATTR,
+ DBGFREG_LDTR_BASE,
+ DBGFREG_LDTR_LIMIT,
+ DBGFREG_TR,
+ DBGFREG_TR_ATTR,
+ DBGFREG_TR_BASE,
+ DBGFREG_TR_LIMIT,
+
+ DBGFREG_CR0,
+ DBGFREG_CR2,
+ DBGFREG_CR3,
+ DBGFREG_CR4,
+ DBGFREG_CR8,
+
+ DBGFREG_DR0,
+ DBGFREG_DR1,
+ DBGFREG_DR2,
+ DBGFREG_DR3,
+ DBGFREG_DR6,
+ DBGFREG_DR7,
+
+ /* MSRs: */
+ DBGFREG_MSR_IA32_APICBASE,
+ DBGFREG_MSR_IA32_CR_PAT,
+ DBGFREG_MSR_IA32_PERF_STATUS,
+ DBGFREG_MSR_IA32_SYSENTER_CS,
+ DBGFREG_MSR_IA32_SYSENTER_EIP,
+ DBGFREG_MSR_IA32_SYSENTER_ESP,
+ DBGFREG_MSR_IA32_TSC,
+ DBGFREG_MSR_K6_EFER,
+ DBGFREG_MSR_K6_STAR,
+ DBGFREG_MSR_K8_CSTAR,
+ DBGFREG_MSR_K8_FS_BASE,
+ DBGFREG_MSR_K8_GS_BASE,
+ DBGFREG_MSR_K8_KERNEL_GS_BASE,
+ DBGFREG_MSR_K8_LSTAR,
+ DBGFREG_MSR_K8_SF_MASK,
+ DBGFREG_MSR_K8_TSC_AUX,
+
+ /** The number of registers to pass to DBGFR3RegQueryAll. */
+ DBGFREG_ALL_COUNT,
+
+ /* Misc aliases that doesn't need be part of the 'all' query: */
+ DBGFREG_AH = DBGFREG_ALL_COUNT,
+ DBGFREG_CH,
+ DBGFREG_DH,
+ DBGFREG_BH,
+ DBGFREG_GDTR,
+ DBGFREG_IDTR,
+
+ /** The end of the registers. */
+ DBGFREG_END,
+ /** The usual 32-bit type hack. */
+ DBGFREG_32BIT_HACK = 0x7fffffff
+} DBGFREG;
+/** Pointer to a register identifier. */
+typedef DBGFREG *PDBGFREG;
+/** Pointer to a const register identifier. */
+typedef DBGFREG const *PCDBGFREG;
+
+/**
+ * Register value type.
+ */
+typedef enum DBGFREGVALTYPE
+{
+ DBGFREGVALTYPE_INVALID = 0,
+ /** Unsigned 8-bit register value. */
+ DBGFREGVALTYPE_U8,
+ /** Unsigned 16-bit register value. */
+ DBGFREGVALTYPE_U16,
+ /** Unsigned 32-bit register value. */
+ DBGFREGVALTYPE_U32,
+ /** Unsigned 64-bit register value. */
+ DBGFREGVALTYPE_U64,
+ /** Unsigned 128-bit register value. */
+ DBGFREGVALTYPE_U128,
+ /** Long double register value. */
+ DBGFREGVALTYPE_R80,
+ /** Descriptor table register value. */
+ DBGFREGVALTYPE_DTR,
+ /** End of the valid register value types. */
+ DBGFREGVALTYPE_END,
+ /** The usual 32-bit type hack. */
+ DBGFREGVALTYPE_32BIT_HACK = 0x7fffffff
+} DBGFREGVALTYPE;
+/** Pointer to a register value type. */
+typedef DBGFREGVALTYPE *PDBGFREGVALTYPE;
+
+/**
+ * A generic register value type.
+ */
+typedef union DBGFREGVAL
+{
+ uint8_t u8; /**< The 8-bit view. */
+ uint16_t u16; /**< The 16-bit view. */
+ uint32_t u32; /**< The 32-bit view. */
+ uint64_t u64; /**< The 64-bit view. */
+ RTUINT128U u128; /**< The 128-bit view. */
+ RTFLOAT80U r80; /**< The 80-bit floating point view. */
+ RTFLOAT80U2 r80Ex; /**< The 80-bit floating point view v2. */
+ /** GDTR or LDTR (DBGFREGVALTYPE_DTR). */
+ struct
+ {
+ /** The table address. */
+ uint64_t u64Base;
+ /** The table limit (length minus 1). */
+ uint32_t u32Limit;
+ } dtr;
+
+ uint8_t au8[16]; /**< The 8-bit array view. */
+ uint16_t au16[8]; /**< The 16-bit array view. */
+ uint32_t au32[4]; /**< The 32-bit array view. */
+ uint64_t au64[2]; /**< The 64-bit array view. */
+ RTUINT128U u;
+} DBGFREGVAL;
+/** Pointer to a generic register value type. */
+typedef DBGFREGVAL *PDBGFREGVAL;
+/** Pointer to a const generic register value type. */
+typedef DBGFREGVAL const *PCDBGFREGVAL;
+
+VMMDECL(ssize_t) DBGFR3RegFormatValue(char *pszBuf, size_t cbBuf, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType, bool fSpecial);
+VMMDECL(ssize_t) DBGFR3RegFormatValueEx(char *pszBuf, size_t cbBuf, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType,
+ unsigned uBase, signed int cchWidth, signed int cchPrecision, uint32_t fFlags);
+
+/**
+ * Register sub-field descriptor.
+ */
+typedef struct DBGFREGSUBFIELD
+{
+ /** The name of the sub-field. NULL is used to terminate the array. */
+ const char *pszName;
+ /** The index of the first bit. Ignored if pfnGet is set. */
+ uint8_t iFirstBit;
+ /** The number of bits. Mandatory. */
+ uint8_t cBits;
+ /** The shift count. Not applied when pfnGet is set, but used to
+ * calculate the minimum type. */
+ int8_t cShift;
+ /** Sub-field flags, DBGFREGSUBFIELD_FLAGS_XXX. */
+ uint8_t fFlags;
+ /** Getter (optional). */
+ DECLCALLBACKMEMBER(int, pfnGet)(void *pvUser, struct DBGFREGSUBFIELD const *pSubField, PRTUINT128U puValue);
+ /** Setter (optional). */
+ DECLCALLBACKMEMBER(int, pfnSet)(void *pvUser, struct DBGFREGSUBFIELD const *pSubField, RTUINT128U uValue, RTUINT128U fMask);
+} DBGFREGSUBFIELD;
+/** Pointer to a const register sub-field descriptor. */
+typedef DBGFREGSUBFIELD const *PCDBGFREGSUBFIELD;
+
+/** @name DBGFREGSUBFIELD_FLAGS_XXX
+ * @{ */
+/** The sub-field is read-only. */
+#define DBGFREGSUBFIELD_FLAGS_READ_ONLY UINT8_C(0x01)
+/** @} */
+
+/** Macro for creating a read-write sub-field entry without getters. */
+#define DBGFREGSUBFIELD_RW(a_szName, a_iFirstBit, a_cBits, a_cShift) \
+ { a_szName, a_iFirstBit, a_cBits, a_cShift, 0 /*fFlags*/, NULL /*pfnGet*/, NULL /*pfnSet*/ }
+/** Macro for creating a read-write sub-field entry with getters. */
+#define DBGFREGSUBFIELD_RW_SG(a_szName, a_cBits, a_cShift, a_pfnGet, a_pfnSet) \
+ { a_szName, 0 /*iFirstBit*/, a_cBits, a_cShift, 0 /*fFlags*/, a_pfnGet, a_pfnSet }
+/** Macro for creating a terminator sub-field entry. */
+#define DBGFREGSUBFIELD_TERMINATOR() \
+ { NULL, 0, 0, 0, 0, NULL, NULL }
+
+/**
+ * Register alias descriptor.
+ */
+typedef struct DBGFREGALIAS
+{
+ /** The alias name. NULL is used to terminate the array. */
+ const char *pszName;
+ /** Set to a valid type if the alias has a different type. */
+ DBGFREGVALTYPE enmType;
+} DBGFREGALIAS;
+/** Pointer to a const register alias descriptor. */
+typedef DBGFREGALIAS const *PCDBGFREGALIAS;
+
+/**
+ * Register descriptor.
+ */
+typedef struct DBGFREGDESC
+{
+ /** The normal register name. */
+ const char *pszName;
+ /** The register identifier if this is a CPU register. */
+ DBGFREG enmReg;
+ /** The default register type. */
+ DBGFREGVALTYPE enmType;
+ /** Flags, see DBGFREG_FLAGS_XXX. */
+ uint32_t fFlags;
+ /** The internal register indicator.
+ * For CPU registers this is the offset into the CPUMCTX structure,
+ * thuse the 'off' prefix. */
+ uint32_t offRegister;
+ /** Getter. */
+ DECLCALLBACKMEMBER(int, pfnGet)(void *pvUser, struct DBGFREGDESC const *pDesc, PDBGFREGVAL pValue);
+ /** Setter. */
+ DECLCALLBACKMEMBER(int, pfnSet)(void *pvUser, struct DBGFREGDESC const *pDesc, PCDBGFREGVAL pValue, PCDBGFREGVAL pfMask);
+ /** Aliases (optional). */
+ PCDBGFREGALIAS paAliases;
+ /** Sub fields (optional). */
+ PCDBGFREGSUBFIELD paSubFields;
+} DBGFREGDESC;
+
+/** @name Macros for constructing DBGFREGDESC arrays.
+ * @{ */
+#define DBGFREGDESC_RW(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/, a_offRegister, a_pfnGet, a_pfnSet, NULL /*paAlises*/, NULL /*paSubFields*/ }
+#define DBGFREGDESC_RO(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, NULL /*paAlises*/, NULL /*paSubFields*/ }
+#define DBGFREGDESC_RW_A(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, NULL /*paSubFields*/ }
+#define DBGFREGDESC_RO_A(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, NULL /*paSubFields*/ }
+#define DBGFREGDESC_RW_S(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paSubFields) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/, a_offRegister, a_pfnGet, a_pfnSet, /*paAliases*/, a_paSubFields }
+#define DBGFREGDESC_RO_S(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paSubFields) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, /*paAliases*/, a_paSubFields }
+#define DBGFREGDESC_RW_AS(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, 0 /*fFlags*/, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
+#define DBGFREGDESC_RO_AS(a_szName, a_TypeSuff, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields) \
+ { a_szName, DBGFREG_END, DBGFREGVALTYPE_##a_TypeSuff, DBGFREG_FLAGS_READ_ONLY, a_offRegister, a_pfnGet, a_pfnSet, a_paAliases, a_paSubFields }
+#define DBGFREGDESC_TERMINATOR() \
+ { NULL, DBGFREG_END, DBGFREGVALTYPE_INVALID, 0, 0, NULL, NULL, NULL, NULL }
+/** @} */
+
+
+/** @name DBGFREG_FLAGS_XXX
+ * @{ */
+/** The register is read-only. */
+#define DBGFREG_FLAGS_READ_ONLY RT_BIT_32(0)
+/** @} */
+
+/**
+ * Entry in a batch query or set operation.
+ */
+typedef struct DBGFREGENTRY
+{
+ /** The register identifier. */
+ DBGFREG enmReg;
+ /** The size of the value in bytes. */
+ DBGFREGVALTYPE enmType;
+ /** The register value. The valid view is indicated by enmType. */
+ DBGFREGVAL Val;
+} DBGFREGENTRY;
+/** Pointer to a register entry in a batch operation. */
+typedef DBGFREGENTRY *PDBGFREGENTRY;
+/** Pointer to a const register entry in a batch operation. */
+typedef DBGFREGENTRY const *PCDBGFREGENTRY;
+
+/** Used with DBGFR3Reg* to indicate the hypervisor register set instead of the
+ * guest. */
+#define DBGFREG_HYPER_VMCPUID UINT32_C(0x01000000)
+
+VMMR3DECL(int) DBGFR3RegCpuQueryU8( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t *pu8);
+VMMR3DECL(int) DBGFR3RegCpuQueryU16( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t *pu16);
+VMMR3DECL(int) DBGFR3RegCpuQueryU32( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t *pu32);
+VMMR3DECL(int) DBGFR3RegCpuQueryU64( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64);
+VMMR3DECL(int) DBGFR3RegCpuQueryU128(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint128_t *pu128);
+VMMR3DECL(int) DBGFR3RegCpuQueryLrd( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, long double *plrd);
+VMMR3DECL(int) DBGFR3RegCpuQueryXdtr(PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t *pu64Base, uint16_t *pu16Limit);
+#if 0
+VMMR3DECL(int) DBGFR3RegCpuQueryBatch(PVM pVM,VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs);
+VMMR3DECL(int) DBGFR3RegCpuQueryAll( PVM pVM, VMCPUID idCpu, PDBGFREGENTRY paRegs, size_t cRegs);
+
+VMMR3DECL(int) DBGFR3RegCpuSetU8( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint8_t u8);
+VMMR3DECL(int) DBGFR3RegCpuSetU16( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint16_t u16);
+VMMR3DECL(int) DBGFR3RegCpuSetU32( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint32_t u32);
+VMMR3DECL(int) DBGFR3RegCpuSetU64( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint64_t u64);
+VMMR3DECL(int) DBGFR3RegCpuSetU128( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, uint128_t u128);
+VMMR3DECL(int) DBGFR3RegCpuSetLrd( PVM pVM, VMCPUID idCpu, DBGFREG enmReg, long double lrd);
+VMMR3DECL(int) DBGFR3RegCpuSetBatch( PVM pVM, VMCPUID idCpu, PCDBGFREGENTRY paRegs, size_t cRegs);
+#endif
+
+VMMR3DECL(const char *) DBGFR3RegCpuName(PVM pVM, DBGFREG enmReg, DBGFREGVALTYPE enmType);
+
+VMMR3_INT_DECL(int) DBGFR3RegRegisterCpu(PVM pVM, PVMCPU pVCpu, PCDBGFREGDESC paRegisters, bool fGuestRegs);
+VMMR3DECL(int) DBGFR3RegRegisterDevice(PVM pVM, PCDBGFREGDESC paRegisters, PPDMDEVINS pDevIns, const char *pszPrefix, uint32_t iInstance);
+
+/**
+ * Entry in a named batch query or set operation.
+ */
+typedef struct DBGFREGENTRYNM
+{
+ /** The register name. */
+ const char *pszName;
+ /** The size of the value in bytes. */
+ DBGFREGVALTYPE enmType;
+ /** The register value. The valid view is indicated by enmType. */
+ DBGFREGVAL Val;
+} DBGFREGENTRYNM;
+/** Pointer to a named register entry in a batch operation. */
+typedef DBGFREGENTRYNM *PDBGFREGENTRYNM;
+/** Pointer to a const named register entry in a batch operation. */
+typedef DBGFREGENTRYNM const *PCDBGFREGENTRYNM;
+
+VMMR3DECL(int) DBGFR3RegNmValidate( PVM pVM, VMCPUID idDefCpu, const char *pszReg);
+
+VMMR3DECL(int) DBGFR3RegNmQuery( PVM pVM, VMCPUID idDefCpu, const char *pszReg, PDBGFREGVAL pValue, PDBGFREGVALTYPE penmType);
+VMMR3DECL(int) DBGFR3RegNmQueryU8( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint8_t *pu8);
+VMMR3DECL(int) DBGFR3RegNmQueryU16( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint16_t *pu16);
+VMMR3DECL(int) DBGFR3RegNmQueryU32( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint32_t *pu32);
+VMMR3DECL(int) DBGFR3RegNmQueryU64( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint64_t *pu64);
+VMMR3DECL(int) DBGFR3RegNmQueryU128(PVM pVM, VMCPUID idDefCpu, const char *pszReg, PRTUINT128U pu128);
+/*VMMR3DECL(int) DBGFR3RegNmQueryLrd( PVM pVM, VMCPUID idDefCpu, const char *pszReg, long double *plrd);*/
+VMMR3DECL(int) DBGFR3RegNmQueryXdtr(PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint64_t *pu64Base, uint16_t *pu16Limit);
+VMMR3DECL(int) DBGFR3RegNmQueryBatch(PVM pVM,VMCPUID idDefCpu, PDBGFREGENTRYNM paRegs, size_t cRegs);
+VMMR3DECL(int) DBGFR3RegNmQueryAllCount(PVM pVM, size_t *pcRegs);
+VMMR3DECL(int) DBGFR3RegNmQueryAll( PVM pVM, PDBGFREGENTRYNM paRegs, size_t cRegs);
+
+VMMR3DECL(int) DBGFR3RegNmSet( PVM pVM, VMCPUID idDefCpu, const char *pszReg, PCDBGFREGVAL pValue, DBGFREGVALTYPE enmType);
+VMMR3DECL(int) DBGFR3RegNmSetU8( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint8_t u8);
+VMMR3DECL(int) DBGFR3RegNmSetU16( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint16_t u16);
+VMMR3DECL(int) DBGFR3RegNmSetU32( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint32_t u32);
+VMMR3DECL(int) DBGFR3RegNmSetU64( PVM pVM, VMCPUID idDefCpu, const char *pszReg, uint64_t u64);
+VMMR3DECL(int) DBGFR3RegNmSetU128( PVM pVM, VMCPUID idDefCpu, const char *pszReg, RTUINT128U u128);
+VMMR3DECL(int) DBGFR3RegNmSetLrd( PVM pVM, VMCPUID idDefCpu, const char *pszReg, long double lrd);
+VMMR3DECL(int) DBGFR3RegNmSetBatch( PVM pVM, VMCPUID idDefCpu, PCDBGFREGENTRYNM paRegs, size_t cRegs);
+
+/** @todo add enumeration methods. */
+
+VMMR3DECL(int) DBGFR3RegPrintf( PVM pVM, VMCPUID idDefCpu, char *pszBuf, size_t cbBuf, const char *pszFormat, ...);
+VMMR3DECL(int) DBGFR3RegPrintfV(PVM pVM, VMCPUID idDefCpu, char *pszBuf, size_t cbBuf, const char *pszFormat, va_list va);
+
+
+/**
+ * Guest OS digger interface identifier.
+ *
+ * This is for use together with PDBGFR3QueryInterface and is used to
+ * obtain access to optional interfaces.
+ */
+typedef enum DBGFOSINTERFACE
+{
+ /** The usual invalid entry. */
+ DBGFOSINTERFACE_INVALID = 0,
+ /** Process info. */
+ DBGFOSINTERFACE_PROCESS,
+ /** Thread info. */
+ DBGFOSINTERFACE_THREAD,
+ /** The end of the valid entries. */
+ DBGFOSINTERFACE_END,
+ /** The usual 32-bit type blowup. */
+ DBGFOSINTERFACE_32BIT_HACK = 0x7fffffff
+} DBGFOSINTERFACE;
+/** Pointer to a Guest OS digger interface identifier. */
+typedef DBGFOSINTERFACE *PDBGFOSINTERFACE;
+/** Pointer to a const Guest OS digger interface identifier. */
+typedef DBGFOSINTERFACE const *PCDBGFOSINTERFACE;
+
+
+/**
+ * Guest OS Digger Registration Record.
+ *
+ * This is used with the DBGFR3OSRegister() API.
+ */
+typedef struct DBGFOSREG
+{
+ /** Magic value (DBGFOSREG_MAGIC). */
+ uint32_t u32Magic;
+ /** Flags. Reserved. */
+ uint32_t fFlags;
+ /** The size of the instance data. */
+ uint32_t cbData;
+ /** Operative System name. */
+ char szName[24];
+
+ /**
+ * Constructs the instance.
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pvData Pointer to the instance data.
+ */
+ DECLCALLBACKMEMBER(int, pfnConstruct)(PVM pVM, void *pvData);
+
+ /**
+ * Destroys the instance.
+ *
+ * @param pVM Pointer to the shared VM structure.
+ * @param pvData Pointer to the instance data.
+ */
+ DECLCALLBACKMEMBER(void, pfnDestruct)(PVM pVM, void *pvData);
+
+ /**
+ * Probes the guest memory for OS finger prints.
+ *
+ * No setup or so is performed, it will be followed by a call to pfnInit
+ * or pfnRefresh that should take care of that.
+ *
+ * @returns true if is an OS handled by this module, otherwise false.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pvData Pointer to the instance data.
+ */
+ DECLCALLBACKMEMBER(bool, pfnProbe)(PVM pVM, void *pvData);
+
+ /**
+ * Initializes a fresly detected guest, loading symbols and such useful stuff.
+ *
+ * This is called after pfnProbe.
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pvData Pointer to the instance data.
+ */
+ DECLCALLBACKMEMBER(int, pfnInit)(PVM pVM, void *pvData);
+
+ /**
+ * Refreshes symbols and stuff following a redetection of the same OS.
+ *
+ * This is called after pfnProbe.
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pvData Pointer to the instance data.
+ */
+ DECLCALLBACKMEMBER(int, pfnRefresh)(PVM pVM, void *pvData);
+
+ /**
+ * Terminates an OS when a new (or none) OS has been detected,
+ * and before destruction.
+ *
+ * This is called after pfnProbe and if needed before pfnDestruct.
+ *
+ * @param pVM Pointer to the shared VM structure.
+ * @param pvData Pointer to the instance data.
+ */
+ DECLCALLBACKMEMBER(void, pfnTerm)(PVM pVM, void *pvData);
+
+ /**
+ * Queries the version of the running OS.
+ *
+ * This is only called after pfnInit().
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pvData Pointer to the instance data.
+ * @param pszVersion Where to store the version string.
+ * @param cchVersion The size of the version string buffer.
+ */
+ DECLCALLBACKMEMBER(int, pfnQueryVersion)(PVM pVM, void *pvData, char *pszVersion, size_t cchVersion);
+
+ /**
+ * Queries the pointer to a interface.
+ *
+ * This is called after pfnProbe.
+ *
+ * @returns Pointer to the interface if available, NULL if not available.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pvData Pointer to the instance data.
+ * @param enmIf The interface identifier.
+ */
+ DECLCALLBACKMEMBER(void *, pfnQueryInterface)(PVM pVM, void *pvData, DBGFOSINTERFACE enmIf);
+
+ /** Trailing magic (DBGFOSREG_MAGIC). */
+ uint32_t u32EndMagic;
+} DBGFOSREG;
+/** Pointer to a Guest OS digger registration record. */
+typedef DBGFOSREG *PDBGFOSREG;
+/** Pointer to a const Guest OS digger registration record. */
+typedef DBGFOSREG const *PCDBGFOSREG;
+
+/** Magic value for DBGFOSREG::u32Magic and DBGFOSREG::u32EndMagic. (Hitomi Kanehara) */
+#define DBGFOSREG_MAGIC 0x19830808
+
+VMMR3DECL(int) DBGFR3OSRegister(PVM pVM, PCDBGFOSREG pReg);
+VMMR3DECL(int) DBGFR3OSDeregister(PVM pVM, PCDBGFOSREG pReg);
+VMMR3DECL(int) DBGFR3OSDetect(PVM pVM, char *pszName, size_t cchName);
+VMMR3DECL(int) DBGFR3OSQueryNameAndVersion(PVM pVM, char *pszName, size_t cchName, char *pszVersion, size_t cchVersion);
+VMMR3DECL(void *) DBGFR3OSQueryInterface(PVM pVM, DBGFOSINTERFACE enmIf);
+
+
+VMMR3DECL(int) DBGFR3CoreWrite(PVM pVM, const char *pszFilename, bool fReplaceFile);
+
+/** @} */
+
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/dbgfcorefmt.h b/include/VBox/vmm/dbgfcorefmt.h
new file mode 100644
index 00000000..28f6aec2
--- /dev/null
+++ b/include/VBox/vmm/dbgfcorefmt.h
@@ -0,0 +1,79 @@
+/** @file
+ * DBGF - Debugger Facility, VM Core File Format.
+ */
+
+/*
+ * Copyright (C) 2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_dbgfcore_h
+#define ___VBox_vmm_dbgfcore_h
+
+#include <VBox/types.h>
+#include <VBox/vmm/cpumctx.h>
+#include <iprt/assert.h>
+
+
+RT_C_DECLS_BEGIN
+
+
+/** @addgroup grp_dbgf_corefmt VM Core File Format
+ * @ingroup grp_dbgf
+ *
+ * @todo Add description of the core file format and how the structures in this
+ * file relate to it. Point to CPUMCTX in cpum.h for the CPU state.
+ * @todo Add the note names.
+ *
+ * @{
+ */
+
+/** DBGCORECOREDESCRIPTOR::u32Magic. */
+#define DBGFCORE_MAGIC UINT32_C(0xc01ac0de)
+/** DBGCORECOREDESCRIPTOR::u32FmtVersion. */
+#define DBGFCORE_FMT_VERSION UINT32_C(0x00010000)
+
+/**
+ * The DBGF Core descriptor.
+ */
+typedef struct DBGFCOREDESCRIPTOR
+{
+ /** The core file magic (DBGFCORE_MAGIC) */
+ uint32_t u32Magic;
+ /** The core file format version (DBGFCORE_FMT_VERSION). */
+ uint32_t u32FmtVersion;
+ /** Size of this structure (sizeof(DBGFCOREDESCRIPTOR)). */
+ uint32_t cbSelf;
+ /** VirtualBox version. */
+ uint32_t u32VBoxVersion;
+ /** VirtualBox revision. */
+ uint32_t u32VBoxRevision;
+ /** Number of CPUs. */
+ uint32_t cCpus;
+} DBGFCOREDESCRIPTOR;
+AssertCompileSizeAlignment(DBGFCOREDESCRIPTOR, 8);
+/** Pointer to DBGFCOREDESCRIPTOR data. */
+typedef DBGFCOREDESCRIPTOR *PDBGFCOREDESCRIPTOR;
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/dbgfsel.h b/include/VBox/vmm/dbgfsel.h
new file mode 100644
index 00000000..708666bf
--- /dev/null
+++ b/include/VBox/vmm/dbgfsel.h
@@ -0,0 +1,104 @@
+/** @file
+ * DBGF - Debugger Facility, selector interface partly shared with SELM.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+#ifndef ___VBox_vmm_dbgfsel_h
+#define ___VBox_vmm_dbgfsel_h
+
+#include <VBox/types.h>
+#include <iprt/x86.h>
+
+
+/** @addtogroup grp_dbgf
+ * @{ */
+
+/**
+ * Selector information structure.
+ */
+typedef struct DBGFSELINFO
+{
+ /** The base address.
+ * For gate descriptors, this is the target address. */
+ RTGCPTR GCPtrBase;
+ /** The limit (-1).
+ * For gate descriptors, this is set to zero. */
+ RTGCUINTPTR cbLimit;
+ /** The raw descriptor. */
+ union
+ {
+ X86DESC Raw;
+ X86DESC64 Raw64;
+ } u;
+ /** The selector. */
+ RTSEL Sel;
+ /** The target selector for a gate.
+ * This is 0 if non-gate descriptor. */
+ RTSEL SelGate;
+ /** Flags. */
+ uint32_t fFlags;
+} DBGFSELINFO;
+/** Pointer to a SELM selector information struct. */
+typedef DBGFSELINFO *PDBGFSELINFO;
+/** Pointer to a const SELM selector information struct. */
+typedef const DBGFSELINFO *PCDBGFSELINFO;
+
+/** @name DBGFSELINFO::fFlags
+ * @{ */
+/** The CPU is in real mode. */
+#define DBGFSELINFO_FLAGS_REAL_MODE RT_BIT_32(0)
+/** The CPU is in protected mode. */
+#define DBGFSELINFO_FLAGS_PROT_MODE RT_BIT_32(1)
+/** The CPU is in long mode. */
+#define DBGFSELINFO_FLAGS_LONG_MODE RT_BIT_32(2)
+/** The selector is a hyper selector. */
+#define DBGFSELINFO_FLAGS_HYPER RT_BIT_32(3)
+/** The selector is a gate selector. */
+#define DBGFSELINFO_FLAGS_GATE RT_BIT_32(4)
+/** The selector is invalid. */
+#define DBGFSELINFO_FLAGS_INVALID RT_BIT_32(5)
+/** The selector not present. */
+#define DBGFSELINFO_FLAGS_NOT_PRESENT RT_BIT_32(6)
+/** @} */
+
+
+/**
+ * Tests whether the selector info describes an expand-down selector or now.
+ *
+ * @returns true / false.
+ * @param pSelInfo The selector info.
+ */
+DECLINLINE(bool) DBGFSelInfoIsExpandDown(PCDBGFSELINFO pSelInfo)
+{
+ return (pSelInfo)->u.Raw.Gen.u1DescType
+ && ((pSelInfo)->u.Raw.Gen.u4Type & (X86_SEL_TYPE_DOWN | X86_SEL_TYPE_CODE)) == X86_SEL_TYPE_DOWN;
+}
+
+
+VMMR3DECL(int) DBGFR3SelInfoValidateCS(PCDBGFSELINFO pSelInfo, RTSEL SelCPL);
+
+/** @} */
+
+#endif
+
diff --git a/include/VBox/vmm/dbgftrace.h b/include/VBox/vmm/dbgftrace.h
new file mode 100644
index 00000000..df9b15de
--- /dev/null
+++ b/include/VBox/vmm/dbgftrace.h
@@ -0,0 +1,143 @@
+/** @file
+ * DBGF - Debugger Facility.
+ */
+
+/*
+ * Copyright (C) 2006-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_dbgftrace_h
+#define ___VBox_vmm_dbgftrace_h
+
+#include <iprt/trace.h>
+#include <VBox/types.h>
+
+RT_C_DECLS_BEGIN
+/** @addgroup grp_dbgf_trace Tracing
+ * @ingroup grp_dbgf
+ *
+ * @{
+ */
+
+#if (defined(RTTRACE_ENABLED) || DBGFTRACE_ENABLED) && !defined(DBGFTRACE_DISABLED)
+# undef DBGFTRACE_ENABLED
+# undef DBGFTRACE_DISABLED
+# define DBGFTRACE_ENABLED
+#else
+# undef DBGFTRACE_ENABLED
+# undef DBGFTRACE_DISABLED
+# define DBGFTRACE_DISABLED
+#endif
+
+VMMDECL(int) DBGFR3TraceConfig(PVM pVM, const char *pszConfig);
+
+
+/** @name VMM Internal Trace Macros
+ * @remarks The user of these macros is responsible of including VBox/vmm/vm.h.
+ * @{
+ */
+/**
+ * Records a 64-bit unsigned integer together with a tag string.
+ */
+#ifdef DBGFTRACE_ENABLED
+# define DBGFTRACE_U64_TAG(a_pVM, a_u64, a_pszTag) \
+ do { RTTraceBufAddMsgF((a_pVM)->CTX_SUFF(hTraceBuf), "%'llu %s", (a_u64), (a_pszTag)); } while (0)
+#else
+# define DBGFTRACE_U64_TAG(a_pVM, a_u64, a_pszTag) do { } while (0)
+#endif
+
+/**
+ * Records a 64-bit unsigned integer together with two tag strings.
+ */
+#ifdef DBGFTRACE_ENABLED
+# define DBGFTRACE_U64_TAG2(a_pVM, a_u64, a_pszTag1, a_pszTag2) \
+ do { RTTraceBufAddMsgF((a_pVM)->CTX_SUFF(hTraceBuf), "%'llu %s %s", (a_u64), (a_pszTag1), (a_pszTag2)); } while (0)
+#else
+# define DBGFTRACE_U64_TAG2(a_pVM, a_u64, a_pszTag1, a_pszTag2) do { } while (0)
+#endif
+
+/**
+ * Records the current source position.
+ */
+#ifdef DBGFTRACE_ENABLED
+# define DBGFTRACE_POS(a_pVM) \
+ do { RTTraceBufAddPos((a_pVM)->CTX_SUFF(hTraceBuf), RT_SRC_POS); } while (0)
+#else
+# define DBGFTRACE_POS(a_pVM) do { } while (0)
+#endif
+
+/**
+ * Records the current source position along with a 64-bit unsigned integer.
+ */
+#ifdef DBGFTRACE_ENABLED
+# define DBGFTRACE_POS_U64(a_pVM, a_u64) \
+ do { RTTraceBufAddPosMsgF((a_pVM)->CTX_SUFF(hTraceBuf), RT_SRC_POS, "%'llu", (a_u64)); } while (0)
+#else
+# define DBGFTRACE_POS_U64(a_pVM, a_u64) do { } while (0)
+#endif
+/** @} */
+
+
+/** @name Tracing Macors for PDM Devices, Drivers and USB Devices.
+ * @{
+ */
+
+/**
+ * Get the trace buffer handle.
+ * @param a_pIns The instance (pDevIns, pDrvIns or pUsbIns).
+ */
+#define DBGFTRACE_PDM_TRACEBUF(a_pIns) ( (a_pIns)->CTX_SUFF(pHlp)->pfnDBGFTraceBuf((a_pIns)) )
+
+/**
+ * Records a tagged 64-bit unsigned integer.
+ */
+#ifdef DBGFTRACE_ENABLED
+# define DBGFTRACE_PDM_U64_TAG(a_pIns, a_u64, a_pszTag) \
+ do { RTTraceBufAddMsgF(DBGFTRACE_PDM_TRACEBUF(a_pIns), "%'llu %s", (a_u64), (a_pszTag)); } while (0)
+#else
+# define DBGFTRACE_PDM_U64_TAG(a_pIns, a_u64, a_pszTag) do { } while (0)
+#endif
+
+/**
+ * Records the current source position.
+ */
+#ifdef DBGFTRACE_ENABLED
+# define DBGFTRACE_PDM_POS(a_pIns) \
+ do { RTTraceBufAddPos(DBGFTRACE_PDM_TRACEBUF(a_pIns), RT_SRC_POS); } while (0)
+#else
+# define DBGFTRACE_PDM_POS(a_pIns) do { } while (0)
+#endif
+
+/**
+ * Records the current source position along with a 64-bit unsigned integer.
+ */
+#ifdef DBGFTRACE_ENABLED
+# define DBGFTRACE_PDM_POS_U64(a_pIns, a_u64) \
+ do { RTTraceBufAddPosMsgF(DBGFTRACE_PDM_TRACEBUF(a_pIns), RT_SRC_POS, "%'llu", (a_u64)); } while (0)
+#else
+# define DBGFTRACE_PDM_POS_U64(a_pIns, a_u64) do { } while (0)
+#endif
+/** @} */
+
+
+/** @} */
+RT_C_DECLS_END
+
+#endif
diff --git a/include/VBox/vmm/em.h b/include/VBox/vmm/em.h
new file mode 100644
index 00000000..a0efe5fc
--- /dev/null
+++ b/include/VBox/vmm/em.h
@@ -0,0 +1,276 @@
+/** @file
+ * EM - Execution Monitor.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_em_h
+#define ___VBox_vmm_em_h
+
+#include <VBox/types.h>
+#include <VBox/vmm/trpm.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_em The Execution Monitor / Manager API
+ * @{
+ */
+
+/** Enable to allow V86 code to run in raw mode. */
+#define VBOX_RAW_V86
+
+/**
+ * The Execution Manager State.
+ *
+ * @remarks This is used in the saved state!
+ */
+typedef enum EMSTATE
+{
+ /** Not yet started. */
+ EMSTATE_NONE = 1,
+ /** Raw-mode execution. */
+ EMSTATE_RAW,
+ /** Hardware accelerated raw-mode execution. */
+ EMSTATE_HWACC,
+ /** Value reserved for future use (used to be PARAV). */
+ EMSTATE_RESERVED,
+ /** Recompiled mode execution. */
+ EMSTATE_REM,
+ /** Execution is halted. (waiting for interrupt) */
+ EMSTATE_HALTED,
+ /** Application processor execution is halted. (waiting for startup IPI (SIPI)) */
+ EMSTATE_WAIT_SIPI,
+ /** Execution is suspended. */
+ EMSTATE_SUSPENDED,
+ /** The VM is terminating. */
+ EMSTATE_TERMINATING,
+ /** Guest debug event from raw-mode is being processed. */
+ EMSTATE_DEBUG_GUEST_RAW,
+ /** Guest debug event from hardware accelerated mode is being processed. */
+ EMSTATE_DEBUG_GUEST_HWACC,
+ /** Guest debug event from recompiled-mode is being processed. */
+ EMSTATE_DEBUG_GUEST_REM,
+ /** Hypervisor debug event being processed. */
+ EMSTATE_DEBUG_HYPER,
+ /** The VM has encountered a fatal error. (And everyone is panicing....) */
+ EMSTATE_GURU_MEDITATION,
+ /** Just a hack to ensure that we get a 32-bit integer. */
+ EMSTATE_MAKE_32BIT_HACK = 0x7fffffff
+} EMSTATE;
+
+
+/**
+ * EMInterpretInstructionCPU execution modes.
+ */
+typedef enum
+{
+ /** Only supervisor code (CPL=0). */
+ EMCODETYPE_SUPERVISOR,
+ /** User-level code only. */
+ EMCODETYPE_USER,
+ /** Supervisor and user-level code (use with great care!). */
+ EMCODETYPE_ALL,
+ /** Just a hack to ensure that we get a 32-bit integer. */
+ EMCODETYPE_32BIT_HACK = 0x7fffffff
+} EMCODETYPE;
+
+VMMDECL(EMSTATE) EMGetState(PVMCPU pVCpu);
+VMMDECL(void) EMSetState(PVMCPU pVCpu, EMSTATE enmNewState);
+
+/** @name Callback handlers for instruction emulation functions.
+ * These are placed here because IOM wants to use them as well.
+ * @{
+ */
+typedef DECLCALLBACK(uint32_t) FNEMULATEPARAM2UINT32(void *pvParam1, uint64_t val2);
+typedef FNEMULATEPARAM2UINT32 *PFNEMULATEPARAM2UINT32;
+typedef DECLCALLBACK(uint32_t) FNEMULATEPARAM2(void *pvParam1, size_t val2);
+typedef FNEMULATEPARAM2 *PFNEMULATEPARAM2;
+typedef DECLCALLBACK(uint32_t) FNEMULATEPARAM3(void *pvParam1, uint64_t val2, size_t val3);
+typedef FNEMULATEPARAM3 *PFNEMULATEPARAM3;
+typedef DECLCALLBACK(int) FNEMULATELOCKPARAM2(void *pvParam1, uint64_t val2, RTGCUINTREG32 *pf);
+typedef FNEMULATELOCKPARAM2 *PFNEMULATELOCKPARAM2;
+typedef DECLCALLBACK(int) FNEMULATELOCKPARAM3(void *pvParam1, uint64_t val2, size_t cb, RTGCUINTREG32 *pf);
+typedef FNEMULATELOCKPARAM3 *PFNEMULATELOCKPARAM3;
+/** @} */
+
+
+/**
+ * Checks if raw ring-3 execute mode is enabled.
+ *
+ * @returns true if enabled.
+ * @returns false if disabled.
+ * @param pVM The VM to operate on.
+ */
+#define EMIsRawRing3Enabled(pVM) (!(pVM)->fRecompileUser)
+
+/**
+ * Checks if raw ring-0 execute mode is enabled.
+ *
+ * @returns true if enabled.
+ * @returns false if disabled.
+ * @param pVM The VM to operate on.
+ */
+#define EMIsRawRing0Enabled(pVM) (!(pVM)->fRecompileSupervisor)
+
+/**
+ * Checks if execution with hardware assisted virtualization is enabled.
+ *
+ * @returns true if enabled.
+ * @returns false if disabled.
+ * @param pVM The VM to operate on.
+ */
+#define EMIsHwVirtExecutionEnabled(pVM) (!(pVM)->fRecompileSupervisor && !(pVM)->fRecompileUser)
+
+/**
+ * Checks if execution of supervisor code should be done in the
+ * recompiler or not.
+ *
+ * @returns true if enabled.
+ * @returns false if disabled.
+ * @param pVM The VM to operate on.
+ */
+#define EMIsSupervisorCodeRecompiled(pVM) ((pVM)->fRecompileSupervisor)
+
+VMMDECL(void) EMSetInhibitInterruptsPC(PVMCPU pVCpu, RTGCUINTPTR PC);
+VMMDECL(RTGCUINTPTR) EMGetInhibitInterruptsPC(PVMCPU pVCpu);
+VMMDECL(int) EMInterpretDisasCurrent(PVM pVM, PVMCPU pVCpu, PDISCPUSTATE pCpu, unsigned *pcbInstr);
+VMMDECL(int) EMInterpretDisasOneEx(PVM pVM, PVMCPU pVCpu, RTGCUINTPTR GCPtrInstr, PCCPUMCTXCORE pCtxCore,
+ PDISCPUSTATE pDISState, unsigned *pcbInstr);
+VMMDECL(VBOXSTRICTRC) EMInterpretInstruction(PVMCPU pVCpu, PCPUMCTXCORE pCoreCtx, RTGCPTR pvFault);
+VMMDECL(VBOXSTRICTRC) EMInterpretInstructionEx(PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, uint32_t *pcbWritten);
+VMMDECL(VBOXSTRICTRC) EMInterpretInstructionDisasState(PVMCPU pVCpu, PDISCPUSTATE pDis, PCPUMCTXCORE pCoreCtx, RTGCPTR pvFault, EMCODETYPE enmCodeType);
+
+#ifdef IN_RC
+VMMDECL(int) EMInterpretIretV86ForPatm(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame);
+#endif
+
+VMMDECL(int) EMInterpretCpuId(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame);
+VMMDECL(int) EMInterpretRdtsc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame);
+VMMDECL(int) EMInterpretRdpmc(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame);
+VMMDECL(int) EMInterpretRdtscp(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
+VMMDECL(VBOXSTRICTRC) EMInterpretInvlpg(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pAddrGC);
+VMMDECL(VBOXSTRICTRC) EMInterpretMWait(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame);
+VMMDECL(int) EMInterpretMonitor(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame);
+VMMDECL(int) EMInterpretDRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegDrx, uint32_t SrcRegGen);
+VMMDECL(int) EMInterpretDRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegDrx);
+VMMDECL(int) EMInterpretCRxWrite(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegCrx, uint32_t SrcRegGen);
+VMMDECL(int) EMInterpretCRxRead(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t DestRegGen, uint32_t SrcRegCrx);
+VMMDECL(int) EMInterpretLMSW(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint16_t u16Data);
+VMMDECL(int) EMInterpretCLTS(PVM pVM, PVMCPU pVCpu);
+#ifndef VBOX_WITH_IEM
+VMMDECL(int) EMInterpretRdmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame);
+VMMDECL(int) EMInterpretWrmsr(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame);
+#endif /* !VBOX_WITH_IEM */
+VMM_INT_DECL(bool) EMShouldContinueAfterHalt(PVMCPU pVCpu, PCPUMCTX pCtx);
+VMM_INT_DECL(int) EMMonitorWaitPrepare(PVMCPU pVCpu, uint64_t rax, uint64_t rcx, uint64_t rdx);
+VMM_INT_DECL(int) EMMonitorWaitPerform(PVMCPU pVCpu, uint64_t rax, uint64_t rcx);
+
+/** @name Assembly routines
+ * @{ */
+VMMDECL(uint32_t) EMEmulateCmp(uint32_t u32Param1, uint64_t u64Param2, size_t cb);
+VMMDECL(uint32_t) EMEmulateAnd(void *pvParam1, uint64_t u64Param2, size_t cb);
+VMMDECL(uint32_t) EMEmulateInc(void *pvParam1, size_t cb);
+VMMDECL(uint32_t) EMEmulateDec(void *pvParam1, size_t cb);
+VMMDECL(uint32_t) EMEmulateOr(void *pvParam1, uint64_t u64Param2, size_t cb);
+VMMDECL(int) EMEmulateLockOr(void *pvParam1, uint64_t u64Param2, size_t cbSize, RTGCUINTREG32 *pf);
+VMMDECL(uint32_t) EMEmulateXor(void *pvParam1, uint64_t u64Param2, size_t cb);
+VMMDECL(int) EMEmulateLockXor(void *pvParam1, uint64_t u64Param2, size_t cbSize, RTGCUINTREG32 *pf);
+VMMDECL(uint32_t) EMEmulateAdd(void *pvParam1, uint64_t u64Param2, size_t cb);
+VMMDECL(int) EMEmulateLockAnd(void *pvParam1, uint64_t u64Param2, size_t cbSize, RTGCUINTREG32 *pf);
+VMMDECL(uint32_t) EMEmulateSub(void *pvParam1, uint64_t u64Param2, size_t cb);
+VMMDECL(uint32_t) EMEmulateAdcWithCarrySet(void *pvParam1, uint64_t u64Param2, size_t cb);
+VMMDECL(uint32_t) EMEmulateBtr(void *pvParam1, uint64_t u64Param2);
+VMMDECL(int) EMEmulateLockBtr(void *pvParam1, uint64_t u64Param2, RTGCUINTREG32 *pf);
+VMMDECL(uint32_t) EMEmulateBts(void *pvParam1, uint64_t u64Param2);
+VMMDECL(uint32_t) EMEmulateBtc(void *pvParam1, uint64_t u64Param2);
+VMMDECL(uint32_t) EMEmulateCmpXchg(void *pvParam1, uint64_t *pu32Param2, uint64_t u32Param3, size_t cbSize);
+VMMDECL(uint32_t) EMEmulateLockCmpXchg(void *pvParam1, uint64_t *pu64Param2, uint64_t u64Param3, size_t cbSize);
+VMMDECL(uint32_t) EMEmulateCmpXchg8b(void *pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX);
+VMMDECL(uint32_t) EMEmulateLockCmpXchg8b(void *pu32Param1, uint32_t *pEAX, uint32_t *pEDX, uint32_t uEBX, uint32_t uECX);
+VMMDECL(uint32_t) EMEmulateXAdd(void *pvParam1, void *pvParam2, size_t cbOp);
+VMMDECL(uint32_t) EMEmulateLockXAdd(void *pvParam1, void *pvParam2, size_t cbOp);
+/** @} */
+
+/** @name REM locking routines
+ * @{ */
+VMMDECL(void) EMRemUnlock(PVM pVM);
+VMMDECL(void) EMRemLock(PVM pVM);
+VMMDECL(bool) EMRemIsLockOwner(PVM pVM);
+VMMDECL(int) EMRemTryLock(PVM pVM);
+/** @} */
+
+#ifdef IN_RING3
+/** @defgroup grp_em_r3 The EM Host Context Ring-3 API
+ * @ingroup grp_em
+ * @{
+ */
+VMMR3DECL(int) EMR3Init(PVM pVM);
+VMMR3DECL(void) EMR3Relocate(PVM pVM);
+VMMR3DECL(void) EMR3ResetCpu(PVMCPU pVCpu);
+VMMR3DECL(void) EMR3Reset(PVM pVM);
+VMMR3DECL(int) EMR3Term(PVM pVM);
+VMMR3DECL(DECLNORETURN(void)) EMR3FatalError(PVMCPU pVCpu, int rc);
+VMMR3DECL(int) EMR3ExecuteVM(PVM pVM, PVMCPU pVCpu);
+VMMR3DECL(int) EMR3CheckRawForcedActions(PVM pVM, PVMCPU pVCpu);
+VMMR3DECL(int) EMR3Interpret(PVM pVM);
+
+/**
+ * Command argument for EMR3RawSetMode().
+ *
+ * It's possible to extend this interface to change several
+ * execution modes at once should the need arise.
+ */
+typedef enum EMEXECPOLICY
+{
+ /** The customary invalid zero entry. */
+ EMEXECPOLICY_INVALID = 0,
+ /** Whether to recompile ring-0 code or execute it in raw/hm. */
+ EMEXECPOLICY_RECOMPILE_RING0,
+ /** Whether to recompile ring-3 code or execute it in raw/hm. */
+ EMEXECPOLICY_RECOMPILE_RING3,
+ /** End of valid value (not included). */
+ EMEXECPOLICY_END,
+ /** The customary 32-bit type blowup. */
+ EMEXECPOLICY_32BIT_HACK = 0x7fffffff
+} EMEXECPOLICY;
+
+VMMR3DECL(int) EMR3SetExecutionPolicy(PVM pVM, EMEXECPOLICY enmPolicy, bool fEnforce);
+/** @} */
+#endif /* IN_RING3 */
+
+
+#ifdef IN_RC
+/** @defgroup grp_em_gc The EM Guest Context API
+ * @ingroup grp_em
+ * @{
+ */
+VMMRCDECL(int) EMGCTrap(PVM pVM, unsigned uTrap, PCPUMCTXCORE pRegFrame);
+/** @} */
+#endif /* IN_RC */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/ftm.h b/include/VBox/vmm/ftm.h
new file mode 100644
index 00000000..2fc1ccfe
--- /dev/null
+++ b/include/VBox/vmm/ftm.h
@@ -0,0 +1,71 @@
+/** @file
+ * FTM - Fault Tolerance Manager.
+ */
+
+/*
+ * Copyright (C) 2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_ftm_h
+#define ___VBox_vmm_ftm_h
+
+#include <VBox/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_ftm The Fault Tolerance Monitor / Manager API
+ * @{
+ */
+
+/**
+ * Fault tolerance checkpoint type.
+ */
+typedef enum FTMCHECKPOINTTYPE
+{
+ FTMCHECKPOINTTYPE_NETWORK,
+ FTMCHECKPOINTTYPE_STORAGE,
+ FTMCHECKPOINTTYPE_32BIT_HACK = 0x7fffffff
+} FTMCHECKPOINTTYPE;
+
+VMMDECL(bool) FTMIsDeltaLoadSaveActive(PVM pVM);
+VMMDECL(int) FTMSetCheckpoint(PVM pVM, FTMCHECKPOINTTYPE enmType);
+
+#ifdef IN_RING3
+/** @defgroup grp_ftm_r3 The FTM Host Context Ring-3 API
+ * @ingroup grp_ftm
+ * @{
+ */
+VMMR3DECL(int) FTMR3PowerOn(PVM pVM, bool fMaster, unsigned uInterval, const char *pszAddress, unsigned uPort, const char *pszPassword);
+VMMR3DECL(int) FTMR3Init(PVM pVM);
+VMMR3DECL(int) FTMR3Term(PVM pVM);
+VMMR3DECL(int) FTMR3CancelStandby(PVM pVM);
+VMMR3DECL(int) FTMR3SetCheckpoint(PVM pVM, FTMCHECKPOINTTYPE enmType);
+
+#endif /* IN_RING3 */
+
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/gmm.h b/include/VBox/vmm/gmm.h
new file mode 100644
index 00000000..0f93c94a
--- /dev/null
+++ b/include/VBox/vmm/gmm.h
@@ -0,0 +1,809 @@
+/** @file
+ * GMM - The Global Memory Manager.
+ */
+
+/*
+ * Copyright (C) 2007-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_gmm_h
+#define ___VBox_vmm_gmm_h
+
+#include <VBox/vmm/gvmm.h>
+#include <VBox/sup.h>
+#include <VBox/param.h>
+#include <VBox/ostypes.h>
+#include <VBox/VMMDev.h>
+#include <iprt/avl.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_gmm GMM - The Global Memory Manager
+ * @{
+ */
+
+/** @def IN_GMM_R0
+ * Used to indicate whether we're inside the same link module as the ring 0
+ * part of the Global Memory Manager or not.
+ */
+#ifdef DOXYGEN_RUNNING
+# define IN_GMM_R0
+#endif
+/** @def GMMR0DECL
+ * Ring 0 GMM export or import declaration.
+ * @param type The return type of the function declaration.
+ */
+#ifdef IN_GMM_R0
+# define GMMR0DECL(type) DECLEXPORT(type) VBOXCALL
+#else
+# define GMMR0DECL(type) DECLIMPORT(type) VBOXCALL
+#endif
+
+/** @def IN_GMM_R3
+ * Used to indicate whether we're inside the same link module as the ring 3
+ * part of the Global Memory Manager or not.
+ */
+#ifdef DOXYGEN_RUNNING
+# define IN_GMM_R3
+#endif
+/** @def GMMR3DECL
+ * Ring 3 GMM export or import declaration.
+ * @param type The return type of the function declaration.
+ */
+#ifdef IN_GMM_R3
+# define GMMR3DECL(type) DECLEXPORT(type) VBOXCALL
+#else
+# define GMMR3DECL(type) DECLIMPORT(type) VBOXCALL
+#endif
+
+
+/** The chunk shift. (2^21 = 2 MB) */
+#define GMM_CHUNK_SHIFT 21
+/** The allocation chunk size. */
+#define GMM_CHUNK_SIZE (1U << GMM_CHUNK_SHIFT)
+/** The allocation chunk size in pages. */
+#define GMM_CHUNK_NUM_PAGES (1U << (GMM_CHUNK_SHIFT - PAGE_SHIFT))
+/** The shift factor for converting a page id into a chunk id. */
+#define GMM_CHUNKID_SHIFT (GMM_CHUNK_SHIFT - PAGE_SHIFT)
+/** The last valid Chunk ID value. */
+#define GMM_CHUNKID_LAST (GMM_PAGEID_LAST >> GMM_CHUNKID_SHIFT)
+/** The last valid Page ID value.
+ * The current limit is 2^28 - 1, or almost 1TB if you like.
+ * The constraints are currently dictated by PGMPAGE. */
+#define GMM_PAGEID_LAST (RT_BIT_32(28) - 1)
+/** Mask out the page index from the Page ID. */
+#define GMM_PAGEID_IDX_MASK ((1U << GMM_CHUNKID_SHIFT) - 1)
+/** The NIL Chunk ID value. */
+#define NIL_GMM_CHUNKID 0
+/** The NIL Page ID value. */
+#define NIL_GMM_PAGEID 0
+
+#if 0 /* wrong - these are guest page pfns and not page ids! */
+/** Special Page ID used by unassigned pages. */
+#define GMM_PAGEID_UNASSIGNED 0x0fffffffU
+/** Special Page ID used by unsharable pages.
+ * Like MMIO2, shadow and heap. This is for later, obviously. */
+#define GMM_PAGEID_UNSHARABLE 0x0ffffffeU
+/** The end of the valid Page IDs. This is the first special one. */
+#define GMM_PAGEID_END 0x0ffffff0U
+#endif
+
+
+/** @def GMM_GCPHYS_LAST
+ * The last of the valid guest physical address as it applies to GMM pages.
+ *
+ * This must reflect the constraints imposed by the RTGCPHYS type and
+ * the guest page frame number used internally in GMMPAGE.
+ *
+ * @note Note this corresponds to GMM_PAGE_PFN_LAST. */
+#if HC_ARCH_BITS == 64
+# define GMM_GCPHYS_LAST UINT64_C(0x00000fffffff0000) /* 2^44 (16TB) - 0x10000 */
+#else
+# define GMM_GCPHYS_LAST UINT64_C(0x0000000fffff0000) /* 2^36 (64GB) - 0x10000 */
+#endif
+
+/**
+ * Over-commitment policy.
+ */
+typedef enum GMMOCPOLICY
+{
+ /** The usual invalid 0 value. */
+ GMMOCPOLICY_INVALID = 0,
+ /** No over-commitment, fully backed.
+ * The GMM guarantees that it will be able to allocate all of the
+ * guest RAM for a VM with OC policy. */
+ GMMOCPOLICY_NO_OC,
+ /** to-be-determined. */
+ GMMOCPOLICY_TBD,
+ /** The end of the valid policy range. */
+ GMMOCPOLICY_END,
+ /** The usual 32-bit hack. */
+ GMMOCPOLICY_32BIT_HACK = 0x7fffffff
+} GMMOCPOLICY;
+
+/**
+ * VM / Memory priority.
+ */
+typedef enum GMMPRIORITY
+{
+ /** The usual invalid 0 value. */
+ GMMPRIORITY_INVALID = 0,
+ /** High.
+ * When ballooning, ask these VMs last.
+ * When running out of memory, try not to interrupt these VMs. */
+ GMMPRIORITY_HIGH,
+ /** Normal.
+ * When ballooning, don't wait to ask these.
+ * When running out of memory, pause, save and/or kill these VMs. */
+ GMMPRIORITY_NORMAL,
+ /** Low.
+ * When ballooning, maximize these first.
+ * When running out of memory, save or kill these VMs. */
+ GMMPRIORITY_LOW,
+ /** The end of the valid priority range. */
+ GMMPRIORITY_END,
+ /** The custom 32-bit type blowup. */
+ GMMPRIORITY_32BIT_HACK = 0x7fffffff
+} GMMPRIORITY;
+
+
+/**
+ * GMM Memory Accounts.
+ */
+typedef enum GMMACCOUNT
+{
+ /** The customary invalid zero entry. */
+ GMMACCOUNT_INVALID = 0,
+ /** Account with the base allocations. */
+ GMMACCOUNT_BASE,
+ /** Account with the shadow allocations. */
+ GMMACCOUNT_SHADOW,
+ /** Account with the fixed allocations. */
+ GMMACCOUNT_FIXED,
+ /** The end of the valid values. */
+ GMMACCOUNT_END,
+ /** The usual 32-bit value to finish it off. */
+ GMMACCOUNT_32BIT_HACK = 0x7fffffff
+} GMMACCOUNT;
+
+
+/**
+ * Balloon actions.
+ */
+typedef enum
+{
+ /** Invalid zero entry. */
+ GMMBALLOONACTION_INVALID = 0,
+ /** Inflate the balloon. */
+ GMMBALLOONACTION_INFLATE,
+ /** Deflate the balloon. */
+ GMMBALLOONACTION_DEFLATE,
+ /** Puncture the balloon because of VM reset. */
+ GMMBALLOONACTION_RESET,
+ /** End of the valid actions. */
+ GMMBALLOONACTION_END,
+ /** hack forcing the size of the enum to 32-bits. */
+ GMMBALLOONACTION_MAKE_32BIT_HACK = 0x7fffffff
+} GMMBALLOONACTION;
+
+
+/**
+ * A page descriptor for use when freeing pages.
+ * See GMMR0FreePages, GMMR0BalloonedPages.
+ */
+typedef struct GMMFREEPAGEDESC
+{
+ /** The Page ID of the page to be freed. */
+ uint32_t idPage;
+} GMMFREEPAGEDESC;
+/** Pointer to a page descriptor for freeing pages. */
+typedef GMMFREEPAGEDESC *PGMMFREEPAGEDESC;
+
+
+/**
+ * A page descriptor for use when updating and allocating pages.
+ *
+ * This is a bit complicated because we want to do as much as possible
+ * with the same structure.
+ */
+typedef struct GMMPAGEDESC
+{
+ /** The physical address of the page.
+ *
+ * @input GMMR0AllocateHandyPages expects the guest physical address
+ * to update the GMMPAGE structure with. Pass GMM_GCPHYS_UNSHAREABLE
+ * when appropriate and NIL_RTHCPHYS when the page wasn't used
+ * for any specific guest address.
+ *
+ * GMMR0AllocatePage expects the guest physical address to put in
+ * the GMMPAGE structure for the page it allocates for this entry.
+ * Pass NIL_RTHCPHYS and GMM_GCPHYS_UNSHAREABLE as above.
+ *
+ * @output The host physical address of the allocated page.
+ * NIL_RTHCPHYS on allocation failure.
+ *
+ * ASSUMES: sizeof(RTHCPHYS) >= sizeof(RTGCPHYS).
+ */
+ RTHCPHYS HCPhysGCPhys;
+
+ /** The Page ID.
+ *
+ * @intput GMMR0AllocateHandyPages expects the Page ID of the page to
+ * update here. NIL_GMM_PAGEID means no page should be updated.
+ *
+ * GMMR0AllocatePages requires this to be initialized to
+ * NIL_GMM_PAGEID currently.
+ *
+ * @output The ID of the page, NIL_GMM_PAGEID if the allocation failed.
+ */
+ uint32_t idPage;
+
+ /** The Page ID of the shared page was replaced by this page.
+ *
+ * @input GMMR0AllocateHandyPages expects this to indicate a shared
+ * page that has been replaced by this page and should have its
+ * reference counter decremented and perhaps be freed up. Use
+ * NIL_GMM_PAGEID if no shared page was involved.
+ *
+ * All other APIs expects NIL_GMM_PAGEID here.
+ *
+ * @output All APIs sets this to NIL_GMM_PAGEID.
+ */
+ uint32_t idSharedPage;
+} GMMPAGEDESC;
+AssertCompileSize(GMMPAGEDESC, 16);
+/** Pointer to a page allocation. */
+typedef GMMPAGEDESC *PGMMPAGEDESC;
+
+/** GMMPAGEDESC::HCPhysGCPhys value that indicates that the page is unsharable.
+ * @note This corresponds to GMM_PAGE_PFN_UNSHAREABLE. */
+#if HC_ARCH_BITS == 64
+# define GMM_GCPHYS_UNSHAREABLE UINT64_C(0x00000fffffff1000)
+#else
+# define GMM_GCPHYS_UNSHAREABLE UINT64_C(0x0000000fffff1000)
+#endif
+
+
+/**
+ * The allocation sizes.
+ */
+typedef struct GMMVMSIZES
+{
+ /** The number of pages of base memory.
+ * This is the sum of RAM, ROMs and handy pages. */
+ uint64_t cBasePages;
+ /** The number of pages for the shadow pool. (Can be squeezed for memory.) */
+ uint32_t cShadowPages;
+ /** The number of pages for fixed allocations like MMIO2 and the hyper heap. */
+ uint32_t cFixedPages;
+} GMMVMSIZES;
+/** Pointer to a GMMVMSIZES. */
+typedef GMMVMSIZES *PGMMVMSIZES;
+
+
+/**
+ * GMM VM statistics.
+ */
+typedef struct GMMVMSTATS
+{
+ /** The reservations. */
+ GMMVMSIZES Reserved;
+ /** The actual allocations.
+ * This includes both private and shared page allocations. */
+ GMMVMSIZES Allocated;
+
+ /** The current number of private pages. */
+ uint64_t cPrivatePages;
+ /** The current number of shared pages. */
+ uint64_t cSharedPages;
+ /** The current number of ballooned pages. */
+ uint64_t cBalloonedPages;
+ /** The max number of pages that can be ballooned. */
+ uint64_t cMaxBalloonedPages;
+ /** The number of pages we've currently requested the guest to give us.
+ * This is 0 if no pages currently requested. */
+ uint64_t cReqBalloonedPages;
+ /** The number of pages the guest has given us in response to the request.
+ * This is not reset on request completed and may be used in later decisions. */
+ uint64_t cReqActuallyBalloonedPages;
+ /** The number of pages we've currently requested the guest to take back. */
+ uint64_t cReqDeflatePages;
+ /** The number of shareable module tracked by this VM. */
+ uint32_t cShareableModules;
+
+ /** The current over-commitment policy. */
+ GMMOCPOLICY enmPolicy;
+ /** The VM priority for arbitrating VMs in low and out of memory situation.
+ * Like which VMs to start squeezing first. */
+ GMMPRIORITY enmPriority;
+ /** Whether ballooning is enabled or not. */
+ bool fBallooningEnabled;
+ /** Whether shared paging is enabled or not. */
+ bool fSharedPagingEnabled;
+ /** Whether the VM is allowed to allocate memory or not.
+ * This is used when the reservation update request fails or when the VM has
+ * been told to suspend/save/die in an out-of-memory case. */
+ bool fMayAllocate;
+ /** Explicit alignment. */
+ bool afReserved[1];
+
+
+} GMMVMSTATS;
+
+
+/**
+ * The GMM statistics.
+ */
+typedef struct GMMSTATS
+{
+ /** The maximum number of pages we're allowed to allocate
+ * (GMM::cMaxPages). */
+ uint64_t cMaxPages;
+ /** The number of pages that has been reserved (GMM::cReservedPages). */
+ uint64_t cReservedPages;
+ /** The number of pages that we have over-committed in reservations
+ * (GMM::cOverCommittedPages). */
+ uint64_t cOverCommittedPages;
+ /** The number of actually allocated (committed if you like) pages
+ * (GMM::cAllocatedPages). */
+ uint64_t cAllocatedPages;
+ /** The number of pages that are shared. A subset of cAllocatedPages.
+ * (GMM::cSharedPages) */
+ uint64_t cSharedPages;
+ /** The number of pages that are actually shared between VMs.
+ * (GMM:cDuplicatePages) */
+ uint64_t cDuplicatePages;
+ /** The number of pages that are shared that has been left behind by
+ * VMs not doing proper cleanups (GMM::cLeftBehindSharedPages). */
+ uint64_t cLeftBehindSharedPages;
+ /** The number of current ballooned pages (GMM::cBalloonedPages). */
+ uint64_t cBalloonedPages;
+ /** The number of allocation chunks (GMM::cChunks). */
+ uint32_t cChunks;
+ /** The number of freed chunks ever (GMM::cFreedChunks). */
+ uint32_t cFreedChunks;
+ /** The number of shareable modules (GMM:cShareableModules). */
+ uint64_t cShareableModules;
+ /** Space reserved for later. */
+ uint64_t au64Reserved[2];
+
+ /** Statistics for the specified VM. (Zero filled if not requested.) */
+ GMMVMSTATS VMStats;
+} GMMSTATS;
+/** Pointer to the GMM statistics. */
+typedef GMMSTATS *PGMMSTATS;
+/** Const pointer to the GMM statistics. */
+typedef const GMMSTATS *PCGMMSTATS;
+
+
+GMMR0DECL(int) GMMR0Init(void);
+GMMR0DECL(void) GMMR0Term(void);
+GMMR0DECL(void) GMMR0InitPerVMData(PGVM pGVM);
+GMMR0DECL(void) GMMR0CleanupVM(PGVM pGVM);
+GMMR0DECL(int) GMMR0InitialReservation(PVM pVM, VMCPUID idCpu, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages,
+ GMMOCPOLICY enmPolicy, GMMPRIORITY enmPriority);
+GMMR0DECL(int) GMMR0UpdateReservation(PVM pVM, VMCPUID idCpu, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages);
+GMMR0DECL(int) GMMR0AllocateHandyPages(PVM pVM, VMCPUID idCpu, uint32_t cPagesToUpdate, uint32_t cPagesToAlloc, PGMMPAGEDESC paPages);
+GMMR0DECL(int) GMMR0AllocatePages(PVM pVM, VMCPUID idCpu, uint32_t cPages, PGMMPAGEDESC paPages, GMMACCOUNT enmAccount);
+GMMR0DECL(int) GMMR0AllocateLargePage(PVM pVM, VMCPUID idCpu, uint32_t cbPage, uint32_t *pIdPage, RTHCPHYS *pHCPhys);
+GMMR0DECL(int) GMMR0FreePages(PVM pVM, VMCPUID idCpu, uint32_t cPages, PGMMFREEPAGEDESC paPages, GMMACCOUNT enmAccount);
+GMMR0DECL(int) GMMR0FreeLargePage(PVM pVM, VMCPUID idCpu, uint32_t idPage);
+GMMR0DECL(int) GMMR0BalloonedPages(PVM pVM, VMCPUID idCpu, GMMBALLOONACTION enmAction, uint32_t cBalloonedPages);
+GMMR0DECL(int) GMMR0MapUnmapChunk(PVM pVM, uint32_t idChunkMap, uint32_t idChunkUnmap, PRTR3PTR ppvR3);
+GMMR0DECL(int) GMMR0SeedChunk(PVM pVM, VMCPUID idCpu, RTR3PTR pvR3);
+GMMR0DECL(int) GMMR0RegisterSharedModule(PVM pVM, VMCPUID idCpu, VBOXOSFAMILY enmGuestOS, char *pszModuleName, char *pszVersion,
+ RTGCPTR GCBaseAddr, uint32_t cbModule, uint32_t cRegions,
+ struct VMMDEVSHAREDREGIONDESC const *paRegions);
+GMMR0DECL(int) GMMR0UnregisterSharedModule(PVM pVM, VMCPUID idCpu, char *pszModuleName, char *pszVersion, RTGCPTR GCBaseAddr, uint32_t cbModule);
+GMMR0DECL(int) GMMR0UnregisterAllSharedModules(PVM pVM, VMCPUID idCpu);
+GMMR0DECL(int) GMMR0CheckSharedModules(PVM pVM, PVMCPU pVCpu);
+GMMR0DECL(int) GMMR0ResetSharedModules(PVM pVM, VMCPUID idCpu);
+GMMR0DECL(int) GMMR0CheckSharedModulesStart(PVM pVM);
+GMMR0DECL(int) GMMR0CheckSharedModulesEnd(PVM pVM);
+GMMR0DECL(int) GMMR0QueryStatistics(PGMMSTATS pStats, PSUPDRVSESSION pSession);
+GMMR0DECL(int) GMMR0ResetStatistics(PCGMMSTATS pStats, PSUPDRVSESSION pSession);
+
+/**
+ * Request buffer for GMMR0InitialReservationReq / VMMR0_DO_GMM_INITIAL_RESERVATION.
+ * @see GMMR0InitialReservation
+ */
+typedef struct GMMINITIALRESERVATIONREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ uint64_t cBasePages; /**< @see GMMR0InitialReservation */
+ uint32_t cShadowPages; /**< @see GMMR0InitialReservation */
+ uint32_t cFixedPages; /**< @see GMMR0InitialReservation */
+ GMMOCPOLICY enmPolicy; /**< @see GMMR0InitialReservation */
+ GMMPRIORITY enmPriority; /**< @see GMMR0InitialReservation */
+} GMMINITIALRESERVATIONREQ;
+/** Pointer to a GMMR0InitialReservationReq / VMMR0_DO_GMM_INITIAL_RESERVATION request buffer. */
+typedef GMMINITIALRESERVATIONREQ *PGMMINITIALRESERVATIONREQ;
+
+GMMR0DECL(int) GMMR0InitialReservationReq(PVM pVM, VMCPUID idCpu, PGMMINITIALRESERVATIONREQ pReq);
+
+
+/**
+ * Request buffer for GMMR0UpdateReservationReq / VMMR0_DO_GMM_UPDATE_RESERVATION.
+ * @see GMMR0UpdateReservation
+ */
+typedef struct GMMUPDATERESERVATIONREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ uint64_t cBasePages; /**< @see GMMR0UpdateReservation */
+ uint32_t cShadowPages; /**< @see GMMR0UpdateReservation */
+ uint32_t cFixedPages; /**< @see GMMR0UpdateReservation */
+} GMMUPDATERESERVATIONREQ;
+/** Pointer to a GMMR0InitialReservationReq / VMMR0_DO_GMM_INITIAL_RESERVATION request buffer. */
+typedef GMMUPDATERESERVATIONREQ *PGMMUPDATERESERVATIONREQ;
+
+GMMR0DECL(int) GMMR0UpdateReservationReq(PVM pVM, VMCPUID idCpu, PGMMUPDATERESERVATIONREQ pReq);
+
+
+/**
+ * Request buffer for GMMR0AllocatePagesReq / VMMR0_DO_GMM_ALLOCATE_PAGES.
+ * @see GMMR0AllocatePages.
+ */
+typedef struct GMMALLOCATEPAGESREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The account to charge the allocation to. */
+ GMMACCOUNT enmAccount;
+ /** The number of pages to allocate. */
+ uint32_t cPages;
+ /** Array of page descriptors. */
+ GMMPAGEDESC aPages[1];
+} GMMALLOCATEPAGESREQ;
+/** Pointer to a GMMR0AllocatePagesReq / VMMR0_DO_GMM_ALLOCATE_PAGES request buffer. */
+typedef GMMALLOCATEPAGESREQ *PGMMALLOCATEPAGESREQ;
+
+GMMR0DECL(int) GMMR0AllocatePagesReq(PVM pVM, VMCPUID idCpu, PGMMALLOCATEPAGESREQ pReq);
+
+
+/**
+ * Request buffer for GMMR0FreePagesReq / VMMR0_DO_GMM_FREE_PAGES.
+ * @see GMMR0FreePages.
+ */
+typedef struct GMMFREEPAGESREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The account this relates to. */
+ GMMACCOUNT enmAccount;
+ /** The number of pages to free. */
+ uint32_t cPages;
+ /** Array of free page descriptors. */
+ GMMFREEPAGEDESC aPages[1];
+} GMMFREEPAGESREQ;
+/** Pointer to a GMMR0FreePagesReq / VMMR0_DO_GMM_FREE_PAGES request buffer. */
+typedef GMMFREEPAGESREQ *PGMMFREEPAGESREQ;
+
+GMMR0DECL(int) GMMR0FreePagesReq(PVM pVM, VMCPUID idCpu, PGMMFREEPAGESREQ pReq);
+
+/**
+ * Request buffer for GMMR0BalloonedPagesReq / VMMR0_DO_GMM_BALLOONED_PAGES.
+ * @see GMMR0BalloonedPages.
+ */
+typedef struct GMMBALLOONEDPAGESREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The number of ballooned pages. */
+ uint32_t cBalloonedPages;
+ /** Inflate or deflate the balloon. */
+ GMMBALLOONACTION enmAction;
+} GMMBALLOONEDPAGESREQ;
+/** Pointer to a GMMR0BalloonedPagesReq / VMMR0_DO_GMM_BALLOONED_PAGES request buffer. */
+typedef GMMBALLOONEDPAGESREQ *PGMMBALLOONEDPAGESREQ;
+
+GMMR0DECL(int) GMMR0BalloonedPagesReq(PVM pVM, VMCPUID idCpu, PGMMBALLOONEDPAGESREQ pReq);
+
+
+/**
+ * Request buffer for GMMR0QueryHypervisorMemoryStatsReq / VMMR0_DO_GMM_QUERY_VMM_MEM_STATS.
+ * @see GMMR0QueryHypervisorMemoryStatsReq.
+ */
+typedef struct GMMMEMSTATSREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The number of allocated pages (out). */
+ uint64_t cAllocPages;
+ /** The number of free pages (out). */
+ uint64_t cFreePages;
+ /** The number of ballooned pages (out). */
+ uint64_t cBalloonedPages;
+ /** The number of shared pages (out). */
+ uint64_t cSharedPages;
+ /** Maximum nr of pages (out). */
+ uint64_t cMaxPages;
+} GMMMEMSTATSREQ;
+/** Pointer to a GMMR0QueryHypervisorMemoryStatsReq / VMMR0_DO_GMM_QUERY_HYPERVISOR_MEM_STATS request buffer. */
+typedef GMMMEMSTATSREQ *PGMMMEMSTATSREQ;
+
+GMMR0DECL(int) GMMR0QueryHypervisorMemoryStatsReq(PVM pVM, PGMMMEMSTATSREQ pReq);
+GMMR0DECL(int) GMMR0QueryMemoryStatsReq(PVM pVM, VMCPUID idCpu, PGMMMEMSTATSREQ pReq);
+
+/**
+ * Request buffer for GMMR0MapUnmapChunkReq / VMMR0_DO_GMM_MAP_UNMAP_CHUNK.
+ * @see GMMR0MapUnmapChunk
+ */
+typedef struct GMMMAPUNMAPCHUNKREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The chunk to map, NIL_GMM_CHUNKID if unmap only. (IN) */
+ uint32_t idChunkMap;
+ /** The chunk to unmap, NIL_GMM_CHUNKID if map only. (IN) */
+ uint32_t idChunkUnmap;
+ /** Where the mapping address is returned. (OUT) */
+ RTR3PTR pvR3;
+} GMMMAPUNMAPCHUNKREQ;
+/** Pointer to a GMMR0MapUnmapChunkReq / VMMR0_DO_GMM_MAP_UNMAP_CHUNK request buffer. */
+typedef GMMMAPUNMAPCHUNKREQ *PGMMMAPUNMAPCHUNKREQ;
+
+GMMR0DECL(int) GMMR0MapUnmapChunkReq(PVM pVM, PGMMMAPUNMAPCHUNKREQ pReq);
+
+
+/**
+ * Request buffer for GMMR0FreeLargePageReq / VMMR0_DO_GMM_FREE_LARGE_PAGE.
+ * @see GMMR0FreeLargePage.
+ */
+typedef struct GMMFREELARGEPAGEREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The Page ID. */
+ uint32_t idPage;
+} GMMFREELARGEPAGEREQ;
+/** Pointer to a GMMR0FreePagesReq / VMMR0_DO_GMM_FREE_PAGES request buffer. */
+typedef GMMFREELARGEPAGEREQ *PGMMFREELARGEPAGEREQ;
+
+GMMR0DECL(int) GMMR0FreeLargePageReq(PVM pVM, VMCPUID idCpu, PGMMFREELARGEPAGEREQ pReq);
+
+/** Maximum length of the shared module name string, terminator included. */
+#define GMM_SHARED_MODULE_MAX_NAME_STRING 128
+/** Maximum length of the shared module version string, terminator included. */
+#define GMM_SHARED_MODULE_MAX_VERSION_STRING 16
+
+/**
+ * Request buffer for GMMR0RegisterSharedModuleReq / VMMR0_DO_GMM_REGISTER_SHARED_MODULE.
+ * @see GMMR0RegisterSharedModule.
+ */
+typedef struct GMMREGISTERSHAREDMODULEREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Shared module size. */
+ uint32_t cbModule;
+ /** Number of included region descriptors */
+ uint32_t cRegions;
+ /** Base address of the shared module. */
+ RTGCPTR64 GCBaseAddr;
+ /** Guest OS type. */
+ VBOXOSFAMILY enmGuestOS;
+ /** return code. */
+ uint32_t rc;
+ /** Module name */
+ char szName[GMM_SHARED_MODULE_MAX_NAME_STRING];
+ /** Module version */
+ char szVersion[GMM_SHARED_MODULE_MAX_VERSION_STRING];
+ /** Shared region descriptor(s). */
+ VMMDEVSHAREDREGIONDESC aRegions[1];
+} GMMREGISTERSHAREDMODULEREQ;
+/** Pointer to a GMMR0RegisterSharedModuleReq / VMMR0_DO_GMM_REGISTER_SHARED_MODULE request buffer. */
+typedef GMMREGISTERSHAREDMODULEREQ *PGMMREGISTERSHAREDMODULEREQ;
+
+GMMR0DECL(int) GMMR0RegisterSharedModuleReq(PVM pVM, VMCPUID idCpu, PGMMREGISTERSHAREDMODULEREQ pReq);
+
+/**
+ * Shared region descriptor
+ */
+typedef struct GMMSHAREDREGIONDESC
+{
+ /** The page offset where the region starts. */
+ uint32_t off;
+ /** Region size - adjusted by the region offset and rounded up to a
+ * page. */
+ uint32_t cb;
+ /** Pointer to physical GMM page ID array. */
+ uint32_t *paidPages;
+} GMMSHAREDREGIONDESC;
+/** Pointer to a GMMSHAREDREGIONDESC. */
+typedef GMMSHAREDREGIONDESC *PGMMSHAREDREGIONDESC;
+
+
+/**
+ * Shared module registration info (global)
+ */
+typedef struct GMMSHAREDMODULE
+{
+ /** Tree node (keyed by a hash of name & version). */
+ AVLLU32NODECORE Core;
+ /** Shared module size. */
+ uint32_t cbModule;
+ /** Number of included region descriptors */
+ uint32_t cRegions;
+ /** Number of users (VMs). */
+ uint32_t cUsers;
+ /** Guest OS family type. */
+ VBOXOSFAMILY enmGuestOS;
+ /** Module name */
+ char szName[GMM_SHARED_MODULE_MAX_NAME_STRING];
+ /** Module version */
+ char szVersion[GMM_SHARED_MODULE_MAX_VERSION_STRING];
+ /** Shared region descriptor(s). */
+ GMMSHAREDREGIONDESC aRegions[1];
+} GMMSHAREDMODULE;
+/** Pointer to a GMMSHAREDMODULE. */
+typedef GMMSHAREDMODULE *PGMMSHAREDMODULE;
+
+/**
+ * Page descriptor for GMMR0SharedModuleCheckRange
+ */
+typedef struct GMMSHAREDPAGEDESC
+{
+ /** HC Physical address (in/out) */
+ RTHCPHYS HCPhys;
+ /** GC Physical address (in) */
+ RTGCPHYS GCPhys;
+ /** GMM page id. (in/out) */
+ uint32_t idPage;
+ /** CRC32 of the page in strict builds (0 if page not available).
+ * In non-strict build this serves as structure alignment. */
+ uint32_t u32StrictChecksum;
+} GMMSHAREDPAGEDESC;
+/** Pointer to a GMMSHAREDPAGEDESC. */
+typedef GMMSHAREDPAGEDESC *PGMMSHAREDPAGEDESC;
+
+GMMR0DECL(int) GMMR0SharedModuleCheckPage(PGVM pGVM, PGMMSHAREDMODULE pModule, uint32_t idxRegion, uint32_t idxPage,
+ PGMMSHAREDPAGEDESC pPageDesc);
+
+/**
+ * Request buffer for GMMR0UnregisterSharedModuleReq / VMMR0_DO_GMM_UNREGISTER_SHARED_MODULE.
+ * @see GMMR0UnregisterSharedModule.
+ */
+typedef struct GMMUNREGISTERSHAREDMODULEREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Shared module size. */
+ uint32_t cbModule;
+ /** Align at 8 byte boundary. */
+ uint32_t u32Alignment;
+ /** Base address of the shared module. */
+ RTGCPTR64 GCBaseAddr;
+ /** Module name */
+ char szName[GMM_SHARED_MODULE_MAX_NAME_STRING];
+ /** Module version */
+ char szVersion[GMM_SHARED_MODULE_MAX_VERSION_STRING];
+} GMMUNREGISTERSHAREDMODULEREQ;
+/** Pointer to a GMMR0UnregisterSharedModuleReq / VMMR0_DO_GMM_UNREGISTER_SHARED_MODULE request buffer. */
+typedef GMMUNREGISTERSHAREDMODULEREQ *PGMMUNREGISTERSHAREDMODULEREQ;
+
+GMMR0DECL(int) GMMR0UnregisterSharedModuleReq(PVM pVM, VMCPUID idCpu, PGMMUNREGISTERSHAREDMODULEREQ pReq);
+
+#if defined(VBOX_STRICT) && HC_ARCH_BITS == 64
+/**
+ * Request buffer for GMMR0FindDuplicatePageReq / VMMR0_DO_GMM_FIND_DUPLICATE_PAGE.
+ * @see GMMR0FindDuplicatePage.
+ */
+typedef struct GMMFINDDUPLICATEPAGEREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** Page id. */
+ uint32_t idPage;
+ /** Duplicate flag (out) */
+ bool fDuplicate;
+} GMMFINDDUPLICATEPAGEREQ;
+/** Pointer to a GMMR0FindDuplicatePageReq / VMMR0_DO_GMM_FIND_DUPLICATE_PAGE request buffer. */
+typedef GMMFINDDUPLICATEPAGEREQ *PGMMFINDDUPLICATEPAGEREQ;
+
+GMMR0DECL(int) GMMR0FindDuplicatePageReq(PVM pVM, PGMMFINDDUPLICATEPAGEREQ pReq);
+#endif /* VBOX_STRICT && HC_ARCH_BITS == 64 */
+
+
+/**
+ * Request buffer for GMMR0QueryStatisticsReq / VMMR0_DO_GMM_QUERY_STATISTICS.
+ * @see GMMR0QueryStatistics.
+ */
+typedef struct GMMQUERYSTATISTICSSREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The support driver session. */
+ PSUPDRVSESSION pSession;
+ /** The statistics. */
+ GMMSTATS Stats;
+} GMMQUERYSTATISTICSSREQ;
+/** Pointer to a GMMR0QueryStatisticsReq / VMMR0_DO_GMM_QUERY_STATISTICS
+ * request buffer. */
+typedef GMMQUERYSTATISTICSSREQ *PGMMQUERYSTATISTICSSREQ;
+
+GMMR0DECL(int) GMMR0QueryStatisticsReq(PVM pVM, PGMMQUERYSTATISTICSSREQ pReq);
+
+
+/**
+ * Request buffer for GMMR0ResetStatisticsReq / VMMR0_DO_GMM_RESET_STATISTICS.
+ * @see GMMR0ResetStatistics.
+ */
+typedef struct GMMRESETSTATISTICSSREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The support driver session. */
+ PSUPDRVSESSION pSession;
+ /** The statistics to reset.
+ * Any non-zero entry will be reset (if permitted). */
+ GMMSTATS Stats;
+} GMMRESETSTATISTICSSREQ;
+/** Pointer to a GMMR0ResetStatisticsReq / VMMR0_DO_GMM_RESET_STATISTICS
+ * request buffer. */
+typedef GMMRESETSTATISTICSSREQ *PGMMRESETSTATISTICSSREQ;
+
+GMMR0DECL(int) GMMR0ResetStatisticsReq(PVM pVM, PGMMRESETSTATISTICSSREQ pReq);
+
+
+
+#ifdef IN_RING3
+/** @defgroup grp_gmm_r3 The Global Memory Manager Ring-3 API Wrappers
+ * @ingroup grp_gmm
+ * @{
+ */
+GMMR3DECL(int) GMMR3InitialReservation(PVM pVM, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages,
+ GMMOCPOLICY enmPolicy, GMMPRIORITY enmPriority);
+GMMR3DECL(int) GMMR3UpdateReservation(PVM pVM, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages);
+GMMR3DECL(int) GMMR3AllocatePagesPrepare(PVM pVM, PGMMALLOCATEPAGESREQ *ppReq, uint32_t cPages, GMMACCOUNT enmAccount);
+GMMR3DECL(int) GMMR3AllocatePagesPerform(PVM pVM, PGMMALLOCATEPAGESREQ pReq);
+GMMR3DECL(void) GMMR3AllocatePagesCleanup(PGMMALLOCATEPAGESREQ pReq);
+GMMR3DECL(int) GMMR3FreePagesPrepare(PVM pVM, PGMMFREEPAGESREQ *ppReq, uint32_t cPages, GMMACCOUNT enmAccount);
+GMMR3DECL(void) GMMR3FreePagesRePrep(PVM pVM, PGMMFREEPAGESREQ pReq, uint32_t cPages, GMMACCOUNT enmAccount);
+GMMR3DECL(int) GMMR3FreePagesPerform(PVM pVM, PGMMFREEPAGESREQ pReq, uint32_t cActualPages);
+GMMR3DECL(void) GMMR3FreePagesCleanup(PGMMFREEPAGESREQ pReq);
+GMMR3DECL(void) GMMR3FreeAllocatedPages(PVM pVM, GMMALLOCATEPAGESREQ const *pAllocReq);
+GMMR3DECL(int) GMMR3AllocateLargePage(PVM pVM, uint32_t cbPage);
+GMMR3DECL(int) GMMR3FreeLargePage(PVM pVM, uint32_t idPage);
+GMMR3DECL(int) GMMR3MapUnmapChunk(PVM pVM, uint32_t idChunkMap, uint32_t idChunkUnmap, PRTR3PTR ppvR3);
+GMMR3DECL(int) GMMR3SeedChunk(PVM pVM, RTR3PTR pvR3);
+GMMR3DECL(int) GMMR3QueryHypervisorMemoryStats(PVM pVM, uint64_t *pcTotalAllocPages, uint64_t *pcTotalFreePages, uint64_t *pcTotalBalloonPages, uint64_t *puTotalBalloonSize);
+GMMR3DECL(int) GMMR3QueryMemoryStats(PVM pVM, uint64_t *pcAllocPages, uint64_t *pcMaxPages, uint64_t *pcBalloonPages);
+GMMR3DECL(int) GMMR3BalloonedPages(PVM pVM, GMMBALLOONACTION enmAction, uint32_t cBalloonedPages);
+GMMR3DECL(int) GMMR3RegisterSharedModule(PVM pVM, PGMMREGISTERSHAREDMODULEREQ pReq);
+GMMR3DECL(int) GMMR3UnregisterSharedModule(PVM pVM, PGMMUNREGISTERSHAREDMODULEREQ pReq);
+GMMR3DECL(int) GMMR3CheckSharedModules(PVM pVM);
+GMMR3DECL(int) GMMR3ResetSharedModules(PVM pVM);
+
+# if defined(VBOX_STRICT) && HC_ARCH_BITS == 64
+GMMR3DECL(bool) GMMR3IsDuplicatePage(PVM pVM, uint32_t idPage);
+# endif
+
+/** @} */
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/gvm.h b/include/VBox/vmm/gvm.h
new file mode 100644
index 00000000..b0d607de
--- /dev/null
+++ b/include/VBox/vmm/gvm.h
@@ -0,0 +1,124 @@
+/* $Id: gvm.h $ */
+/** @file
+ * GVM - The Global VM Data.
+ */
+
+/*
+ * Copyright (C) 2007-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+#ifndef ___VBox_vmm_gvm_h
+#define ___VBox_vmm_gvm_h
+
+#include <VBox/types.h>
+#include <iprt/thread.h>
+
+
+/** @defgroup grp_gvm GVMCPU - The Global VMCPU Data
+ * @{
+ */
+
+typedef struct GVMCPU
+{
+ /** VCPU id (0 - (pVM->cCpus - 1). */
+ VMCPUID idCpu;
+
+ /** Handle to the EMT thread. */
+ RTNATIVETHREAD hEMT;
+
+ /** The GVMM per vcpu data. */
+ union
+ {
+#ifdef ___GVMMR0Internal_h
+ struct GVMMPERVCPU s;
+#endif
+ uint8_t padding[64];
+ } gvmm;
+} GVMCPU;
+/** Pointer to the GVMCPU data. */
+typedef GVMCPU *PGVMCPU;
+
+/** @} */
+
+/** @defgroup grp_gvm GVM - The Global VM Data
+ * @{
+ */
+
+/**
+ * The Global VM Data.
+ *
+ * This is a ring-0 only structure where we put items we don't need to
+ * share with ring-3 or GC, like for instance various RTR0MEMOBJ handles.
+ *
+ * Unlike VM, there are no special alignment restrictions here. The
+ * paddings are checked by compile time assertions.
+ */
+typedef struct GVM
+{
+ /** Magic / eye-catcher (GVM_MAGIC). */
+ uint32_t u32Magic;
+ /** The global VM handle for this VM. */
+ uint32_t hSelf;
+ /** The ring-0 mapping of the VM structure. */
+ PVM pVM;
+ /** Number of Virtual CPUs, i.e. how many entries there are in aCpus.
+ * Same same as VM::cCpus. */
+ uint32_t cCpus;
+ uint32_t padding;
+
+ /** The GVMM per vm data. */
+ union
+ {
+#ifdef ___GVMMR0Internal_h
+ struct GVMMPERVM s;
+#endif
+ uint8_t padding[256];
+ } gvmm;
+
+ /** The GMM per vm data. */
+ union
+ {
+#ifdef ___GMMR0Internal_h
+ struct GMMPERVM s;
+#endif
+ uint8_t padding[512];
+ } gmm;
+
+ /** The RAWPCIVM per vm data. */
+ union
+ {
+#ifdef ___VBox_rawpci_h
+ struct RAWPCIPERVM s;
+#endif
+ uint8_t padding[64];
+ } rawpci;
+
+
+ /** GVMCPU array for the configured number of virtual CPUs. */
+ GVMCPU aCpus[1];
+} GVM;
+
+/** The GVM::u32Magic value (Wayne Shorter). */
+#define GVM_MAGIC 0x19330825
+
+/** @} */
+
+#endif
diff --git a/include/VBox/vmm/gvmm.h b/include/VBox/vmm/gvmm.h
new file mode 100644
index 00000000..e78d181b
--- /dev/null
+++ b/include/VBox/vmm/gvmm.h
@@ -0,0 +1,268 @@
+/* $Id: gvmm.h $ */
+/** @file
+ * GVMM - The Global VM Manager.
+ */
+
+/*
+ * Copyright (C) 2007-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_gvmm_h
+#define ___VBox_vmm_gvmm_h
+
+#include <VBox/types.h>
+#include <VBox/sup.h>
+#include <iprt/cpuset.h> /* RTCPUSET_MAX_CPUS */
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_GVMM GVMM - The Global VM Manager.
+ * @{
+ */
+
+/** @def IN_GVMM_R0
+ * Used to indicate whether we're inside the same link module as the ring 0
+ * part of the Global VM Manager or not.
+ */
+#ifdef DOXYGEN_RUNNING
+# define IN_GVMM_R0
+#endif
+/** @def GVMMR0DECL
+ * Ring 0 VM export or import declaration.
+ * @param type The return type of the function declaration.
+ */
+#ifdef IN_GVMM_R0
+# define GVMMR0DECL(type) DECLEXPORT(type) VBOXCALL
+#else
+# define GVMMR0DECL(type) DECLIMPORT(type) VBOXCALL
+#endif
+
+/** @def NIL_GVM_HANDLE
+ * The nil GVM VM handle value (VM::hSelf).
+ */
+#define NIL_GVM_HANDLE 0
+
+
+/**
+ * The scheduler statistics
+ */
+typedef struct GVMMSTATSSCHED
+{
+ /** The number of calls to GVMMR0SchedHalt. */
+ uint64_t cHaltCalls;
+ /** The number of times we did go to sleep in GVMMR0SchedHalt. */
+ uint64_t cHaltBlocking;
+ /** The number of times we timed out in GVMMR0SchedHalt. */
+ uint64_t cHaltTimeouts;
+ /** The number of times we didn't go to sleep in GVMMR0SchedHalt. */
+ uint64_t cHaltNotBlocking;
+ /** The number of wake ups done during GVMMR0SchedHalt. */
+ uint64_t cHaltWakeUps;
+
+ /** The number of calls to GVMMR0WakeUp. */
+ uint64_t cWakeUpCalls;
+ /** The number of times the EMT thread wasn't actually halted when GVMMR0WakeUp
+ * was called. */
+ uint64_t cWakeUpNotHalted;
+ /** The number of wake ups done during GVMMR0WakeUp (not counting the explicit
+ * one). */
+ uint64_t cWakeUpWakeUps;
+
+ /** The number of calls to GVMMR0Poke. */
+ uint64_t cPokeCalls;
+ /** The number of times the EMT thread wasn't actually busy when
+ * GVMMR0Poke was called. */
+ uint64_t cPokeNotBusy;
+
+ /** The number of calls to GVMMR0SchedPoll. */
+ uint64_t cPollCalls;
+ /** The number of times the EMT has halted in a GVMMR0SchedPoll call. */
+ uint64_t cPollHalts;
+ /** The number of wake ups done during GVMMR0SchedPoll. */
+ uint64_t cPollWakeUps;
+
+ uint64_t u64Alignment; /**< padding */
+} GVMMSTATSSCHED;
+/** Pointer to the GVMM scheduler statistics. */
+typedef GVMMSTATSSCHED *PGVMMSTATSSCHED;
+
+/**
+ * Per host cpu statistics.
+ */
+typedef struct GVMMSTATSHOSTCPU
+{
+ /** The CPU ID. */
+ RTCPUID idCpu;
+ /** The CPU's set index. */
+ uint32_t idxCpuSet;
+ /** The desired PPT frequency. */
+ uint32_t uDesiredHz;
+ /** The current PPT timer frequency. */
+ uint32_t uTimerHz;
+ /** The number of times the PPT was changed. */
+ uint32_t cChanges;
+ /** The number of times the PPT was started. */
+ uint32_t cStarts;
+} GVMMSTATSHOSTCPU;
+/** Pointer to the GVMM per host CPU statistics. */
+typedef GVMMSTATSHOSTCPU *PGVMMSTATSHOSTCPU;
+
+/**
+ * The GVMM statistics.
+ */
+typedef struct GVMMSTATS
+{
+ /** The VM statistics if a VM was specified. */
+ GVMMSTATSSCHED SchedVM;
+ /** The sum statistics of all VMs accessible to the caller. */
+ GVMMSTATSSCHED SchedSum;
+ /** The number of VMs accessible to the caller. */
+ uint32_t cVMs;
+ /** The number of emulation threads in those VMs. */
+ uint32_t cEMTs;
+ /** Padding. */
+ uint32_t u32Padding;
+ /** The number of valid entries in aHostCpus. */
+ uint32_t cHostCpus;
+ /** Per host CPU statistics. */
+ GVMMSTATSHOSTCPU aHostCpus[RTCPUSET_MAX_CPUS];
+} GVMMSTATS;
+/** Pointer to the GVMM statistics. */
+typedef GVMMSTATS *PGVMMSTATS;
+/** Const pointer to the GVMM statistics. */
+typedef const GVMMSTATS *PCGVMMSTATS;
+
+
+
+GVMMR0DECL(int) GVMMR0Init(void);
+GVMMR0DECL(void) GVMMR0Term(void);
+GVMMR0DECL(int) GVMMR0SetConfig(PSUPDRVSESSION pSession, const char *pszName, uint64_t u64Value);
+GVMMR0DECL(int) GVMMR0QueryConfig(PSUPDRVSESSION pSession, const char *pszName, uint64_t *pu64Value);
+
+GVMMR0DECL(int) GVMMR0CreateVM(PSUPDRVSESSION pSession, uint32_t cCpus, PVM *ppVM);
+GVMMR0DECL(int) GVMMR0InitVM(PVM pVM);
+GVMMR0DECL(void) GVMMR0DoneInitVM(PVM pVM);
+GVMMR0DECL(bool) GVMMR0DoingTermVM(PVM pVM, PGVM pGVM);
+GVMMR0DECL(int) GVMMR0DestroyVM(PVM pVM);
+GVMMR0DECL(int) GVMMR0RegisterVCpu(PVM pVM, VMCPUID idCpu);
+GVMMR0DECL(PGVM) GVMMR0ByHandle(uint32_t hGVM);
+GVMMR0DECL(int) GVMMR0ByVM(PVM pVM, PGVM *ppGVM);
+GVMMR0DECL(int) GVMMR0ByVMAndEMT(PVM pVM, VMCPUID idCpu, PGVM *ppGVM);
+GVMMR0DECL(PVM) GVMMR0GetVMByHandle(uint32_t hGVM);
+GVMMR0DECL(PVM) GVMMR0GetVMByEMT(RTNATIVETHREAD hEMT);
+GVMMR0DECL(int) GVMMR0SchedHalt(PVM pVM, VMCPUID idCpu, uint64_t u64ExpireGipTime);
+GVMMR0DECL(int) GVMMR0SchedWakeUp(PVM pVM, VMCPUID idCpu);
+GVMMR0DECL(int) GVMMR0SchedWakeUpEx(PVM pVM, VMCPUID idCpu, bool fTakeUsedLock);
+GVMMR0DECL(int) GVMMR0SchedPoke(PVM pVM, VMCPUID idCpu);
+GVMMR0DECL(int) GVMMR0SchedPokeEx(PVM pVM, VMCPUID idCpu, bool fTakeUsedLock);
+GVMMR0DECL(int) GVMMR0SchedWakeUpAndPokeCpus(PVM pVM, PCVMCPUSET pSleepSet, PCVMCPUSET pPokeSet);
+GVMMR0DECL(int) GVMMR0SchedPoll(PVM pVM, VMCPUID idCpu, bool fYield);
+GVMMR0DECL(void) GVMMR0SchedUpdatePeriodicPreemptionTimer(PVM pVM, RTCPUID idHostCpu, uint32_t uHz);
+GVMMR0DECL(int) GVMMR0QueryStatistics(PGVMMSTATS pStats, PSUPDRVSESSION pSession, PVM pVM);
+GVMMR0DECL(int) GVMMR0ResetStatistics(PCGVMMSTATS pStats, PSUPDRVSESSION pSession, PVM pVM);
+
+
+/**
+ * Request packet for calling GVMMR0CreateVM.
+ */
+typedef struct GVMMCREATEVMREQ
+{
+ /** The request header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The support driver session. (IN) */
+ PSUPDRVSESSION pSession;
+ /** Number of virtual CPUs for the new VM. (IN) */
+ uint32_t cCpus;
+ /** Pointer to the ring-3 mapping of the shared VM structure on return. (OUT) */
+ PVMR3 pVMR3;
+ /** Pointer to the ring-0 mapping of the shared VM structure on return. (OUT) */
+ PVMR0 pVMR0;
+} GVMMCREATEVMREQ;
+/** Pointer to a GVMMR0CreateVM request packet. */
+typedef GVMMCREATEVMREQ *PGVMMCREATEVMREQ;
+
+GVMMR0DECL(int) GVMMR0CreateVMReq(PGVMMCREATEVMREQ pReq);
+
+
+/**
+ * Request buffer for GVMMR0SchedWakeUpAndPokeCpusReq / VMMR0_DO_GVMM_SCHED_WAKE_UP_AND_POKE_CPUS.
+ * @see GVMMR0SchedWakeUpAndPokeCpus.
+ */
+typedef struct GVMMSCHEDWAKEUPANDPOKECPUSREQ /* nice and unreadable... */
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The sleeper set. */
+ VMCPUSET SleepSet;
+ /** The set of virtual CPUs to poke. */
+ VMCPUSET PokeSet;
+} GVMMSCHEDWAKEUPANDPOKECPUSREQ;
+/** Pointer to a GVMMR0QueryStatisticsReq / VMMR0_DO_GVMM_QUERY_STATISTICS request buffer. */
+typedef GVMMSCHEDWAKEUPANDPOKECPUSREQ *PGVMMSCHEDWAKEUPANDPOKECPUSREQ;
+
+GVMMR0DECL(int) GVMMR0SchedWakeUpAndPokeCpusReq(PVM pVM, PGVMMSCHEDWAKEUPANDPOKECPUSREQ pReq);
+
+
+/**
+ * Request buffer for GVMMR0QueryStatisticsReq / VMMR0_DO_GVMM_QUERY_STATISTICS.
+ * @see GVMMR0QueryStatistics.
+ */
+typedef struct GVMMQUERYSTATISTICSSREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The support driver session. */
+ PSUPDRVSESSION pSession;
+ /** The statistics. */
+ GVMMSTATS Stats;
+} GVMMQUERYSTATISTICSSREQ;
+/** Pointer to a GVMMR0QueryStatisticsReq / VMMR0_DO_GVMM_QUERY_STATISTICS request buffer. */
+typedef GVMMQUERYSTATISTICSSREQ *PGVMMQUERYSTATISTICSSREQ;
+
+GVMMR0DECL(int) GVMMR0QueryStatisticsReq(PVM pVM, PGVMMQUERYSTATISTICSSREQ pReq);
+
+
+/**
+ * Request buffer for GVMMR0ResetStatisticsReq / VMMR0_DO_GVMM_RESET_STATISTICS.
+ * @see GVMMR0ResetStatistics.
+ */
+typedef struct GVMMRESETSTATISTICSSREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The support driver session. */
+ PSUPDRVSESSION pSession;
+ /** The statistics to reset.
+ * Any non-zero entry will be reset (if permitted). */
+ GVMMSTATS Stats;
+} GVMMRESETSTATISTICSSREQ;
+/** Pointer to a GVMMR0ResetStatisticsReq / VMMR0_DO_GVMM_RESET_STATISTICS request buffer. */
+typedef GVMMRESETSTATISTICSSREQ *PGVMMRESETSTATISTICSSREQ;
+
+GVMMR0DECL(int) GVMMR0ResetStatisticsReq(PVM pVM, PGVMMRESETSTATISTICSSREQ pReq);
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/hwacc_svm.h b/include/VBox/vmm/hwacc_svm.h
new file mode 100644
index 00000000..8912e378
--- /dev/null
+++ b/include/VBox/vmm/hwacc_svm.h
@@ -0,0 +1,744 @@
+/** @file
+ * HWACCM - SVM Structures and Definitions. (VMM)
+ */
+
+/*
+ * Copyright (C) 2006-2007 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_svm_h
+#define ___VBox_vmm_svm_h
+
+#include <VBox/types.h>
+#include <VBox/err.h>
+#include <iprt/assert.h>
+#include <iprt/asm.h>
+
+/** @defgroup grp_svm svm Types and Definitions
+ * @ingroup grp_hwaccm
+ * @{
+ */
+
+/** @name SVM features for cpuid 0x8000000a
+ * @{
+ */
+/** Bit 0 - NP - Nested Paging supported. */
+#define AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING RT_BIT(0)
+/** Bit 1 - LbrVirt - Support for saving five debug MSRs. */
+#define AMD_CPUID_SVM_FEATURE_EDX_LBR_VIRT RT_BIT(1)
+/** Bit 2 - SVML - SVM locking bit supported. */
+#define AMD_CPUID_SVM_FEATURE_EDX_SVM_LOCK RT_BIT(2)
+/** Bit 3 - NRIPS - Saving the next instruction pointer is supported. */
+#define AMD_CPUID_SVM_FEATURE_EDX_NRIP_SAVE RT_BIT(3)
+/** Bit 4 - TscRateMsr - Support for MSR TSC ratio. */
+#define AMD_CPUID_SVM_FEATURE_EDX_TSC_RATE_MSR RT_BIT(4)
+/** Bit 5 - VmcbClean - Support VMCB clean bits. */
+#define AMD_CPUID_SVM_FEATURE_EDX_VMCB_CLEAN RT_BIT(5)
+/** Bit 6 - FlushByAsid - Indicate TLB flushing for current ASID only, and that
+ * VMCB.TLB_Control is supported. */
+#define AMD_CPUID_SVM_FEATURE_EDX_FLUSH_BY_ASID RT_BIT(6)
+/** Bit 7 - DecodeAssist - Indicate decode assist is supported. */
+#define AMD_CPUID_SVM_FEATURE_EDX_DECODE_ASSIST RT_BIT(7)
+/** Where did we get this from? */
+#define AMD_CPUID_SVM_FEATURE_EDX_SSE_3_5_DISABLE RT_BIT(9)
+/** Bit 10 - PauseFilter - Indicates support for the PAUSE intercept filter. */
+#define AMD_CPUID_SVM_FEATURE_EDX_PAUSE_FILTER RT_BIT(10)
+/** Bit 12 - PauseFilterThreshold - Indicates support for the PAUSE
+ * intercept filter cycle count threshold. */
+#define AMD_CPUID_SVM_FEATURE_EDX_PAUSE_FILTER_THRESHOLD RT_BIT(12)
+/** @} */
+
+
+/** @name SVM Basic Exit Reasons.
+ * @{
+ */
+/** Invalid guest state in VMCB. */
+#define SVM_EXIT_INVALID -1
+/** Read from CR0-CR15. */
+#define SVM_EXIT_READ_CR0 0x0
+#define SVM_EXIT_READ_CR1 0x1
+#define SVM_EXIT_READ_CR2 0x2
+#define SVM_EXIT_READ_CR3 0x3
+#define SVM_EXIT_READ_CR4 0x4
+#define SVM_EXIT_READ_CR5 0x5
+#define SVM_EXIT_READ_CR6 0x6
+#define SVM_EXIT_READ_CR7 0x7
+#define SVM_EXIT_READ_CR8 0x8
+#define SVM_EXIT_READ_CR9 0x9
+#define SVM_EXIT_READ_CR10 0xA
+#define SVM_EXIT_READ_CR11 0xB
+#define SVM_EXIT_READ_CR12 0xC
+#define SVM_EXIT_READ_CR13 0xD
+#define SVM_EXIT_READ_CR14 0xE
+#define SVM_EXIT_READ_CR15 0xF
+/** Writes to CR0-CR15. */
+#define SVM_EXIT_WRITE_CR0 0x10
+#define SVM_EXIT_WRITE_CR1 0x11
+#define SVM_EXIT_WRITE_CR2 0x12
+#define SVM_EXIT_WRITE_CR3 0x13
+#define SVM_EXIT_WRITE_CR4 0x14
+#define SVM_EXIT_WRITE_CR5 0x15
+#define SVM_EXIT_WRITE_CR6 0x16
+#define SVM_EXIT_WRITE_CR7 0x17
+#define SVM_EXIT_WRITE_CR8 0x18
+#define SVM_EXIT_WRITE_CR9 0x19
+#define SVM_EXIT_WRITE_CR10 0x1A
+#define SVM_EXIT_WRITE_CR11 0x1B
+#define SVM_EXIT_WRITE_CR12 0x1C
+#define SVM_EXIT_WRITE_CR13 0x1D
+#define SVM_EXIT_WRITE_CR14 0x1E
+#define SVM_EXIT_WRITE_CR15 0x1F
+/** Read from DR0-DR15. */
+#define SVM_EXIT_READ_DR0 0x20
+#define SVM_EXIT_READ_DR1 0x21
+#define SVM_EXIT_READ_DR2 0x22
+#define SVM_EXIT_READ_DR3 0x23
+#define SVM_EXIT_READ_DR4 0x24
+#define SVM_EXIT_READ_DR5 0x25
+#define SVM_EXIT_READ_DR6 0x26
+#define SVM_EXIT_READ_DR7 0x27
+#define SVM_EXIT_READ_DR8 0x28
+#define SVM_EXIT_READ_DR9 0x29
+#define SVM_EXIT_READ_DR10 0x2A
+#define SVM_EXIT_READ_DR11 0x2B
+#define SVM_EXIT_READ_DR12 0x2C
+#define SVM_EXIT_READ_DR13 0x2D
+#define SVM_EXIT_READ_DR14 0x2E
+#define SVM_EXIT_READ_DR15 0x2F
+/** Writes to DR0-DR15. */
+#define SVM_EXIT_WRITE_DR0 0x30
+#define SVM_EXIT_WRITE_DR1 0x31
+#define SVM_EXIT_WRITE_DR2 0x32
+#define SVM_EXIT_WRITE_DR3 0x33
+#define SVM_EXIT_WRITE_DR4 0x34
+#define SVM_EXIT_WRITE_DR5 0x35
+#define SVM_EXIT_WRITE_DR6 0x36
+#define SVM_EXIT_WRITE_DR7 0x37
+#define SVM_EXIT_WRITE_DR8 0x38
+#define SVM_EXIT_WRITE_DR9 0x39
+#define SVM_EXIT_WRITE_DR10 0x3A
+#define SVM_EXIT_WRITE_DR11 0x3B
+#define SVM_EXIT_WRITE_DR12 0x3C
+#define SVM_EXIT_WRITE_DR13 0x3D
+#define SVM_EXIT_WRITE_DR14 0x3E
+#define SVM_EXIT_WRITE_DR15 0x3F
+/* Exception 0-31. */
+#define SVM_EXIT_EXCEPTION_0 0x40
+#define SVM_EXIT_EXCEPTION_1 0x41
+#define SVM_EXIT_EXCEPTION_2 0x42
+#define SVM_EXIT_EXCEPTION_3 0x43
+#define SVM_EXIT_EXCEPTION_4 0x44
+#define SVM_EXIT_EXCEPTION_5 0x45
+#define SVM_EXIT_EXCEPTION_6 0x46
+#define SVM_EXIT_EXCEPTION_7 0x47
+#define SVM_EXIT_EXCEPTION_8 0x48
+#define SVM_EXIT_EXCEPTION_9 0x49
+#define SVM_EXIT_EXCEPTION_A 0x4A
+#define SVM_EXIT_EXCEPTION_B 0x4B
+#define SVM_EXIT_EXCEPTION_C 0x4C
+#define SVM_EXIT_EXCEPTION_D 0x4D
+#define SVM_EXIT_EXCEPTION_E 0x4E
+#define SVM_EXIT_EXCEPTION_F 0x4F
+#define SVM_EXIT_EXCEPTION_10 0x50
+#define SVM_EXIT_EXCEPTION_11 0x51
+#define SVM_EXIT_EXCEPTION_12 0x52
+#define SVM_EXIT_EXCEPTION_13 0x53
+#define SVM_EXIT_EXCEPTION_14 0x54
+#define SVM_EXIT_EXCEPTION_15 0x55
+#define SVM_EXIT_EXCEPTION_16 0x56
+#define SVM_EXIT_EXCEPTION_17 0x57
+#define SVM_EXIT_EXCEPTION_18 0x58
+#define SVM_EXIT_EXCEPTION_19 0x59
+#define SVM_EXIT_EXCEPTION_1A 0x5A
+#define SVM_EXIT_EXCEPTION_1B 0x5B
+#define SVM_EXIT_EXCEPTION_1C 0x5C
+#define SVM_EXIT_EXCEPTION_1D 0x5D
+#define SVM_EXIT_EXCEPTION_1E 0x5E
+#define SVM_EXIT_EXCEPTION_1F 0x5F
+/** Physical maskable interrupt. */
+#define SVM_EXIT_INTR 0x60
+/** Non-maskable interrupt. */
+#define SVM_EXIT_NMI 0x61
+/** System Management interrupt. */
+#define SVM_EXIT_SMI 0x62
+/** Physical INIT signal. */
+#define SVM_EXIT_INIT 0x63
+/** Virtual interrupt. */
+#define SVM_EXIT_VINTR 0x64
+/** Write to CR0 that changed any bits other than CR0.TS or CR0.MP. */
+#define SVM_EXIT_CR0_SEL_WRITE 0x65
+/** IDTR read. */
+#define SVM_EXIT_IDTR_READ 0x66
+/** GDTR read. */
+#define SVM_EXIT_GDTR_READ 0x67
+/** LDTR read. */
+#define SVM_EXIT_LDTR_READ 0x68
+/** TR read. */
+#define SVM_EXIT_TR_READ 0x69
+/** IDTR write. */
+#define SVM_EXIT_IDTR_WRITE 0x6A
+/** GDTR write. */
+#define SVM_EXIT_GDTR_WRITE 0x6B
+/** LDTR write. */
+#define SVM_EXIT_LDTR_WRITE 0x6C
+/** TR write. */
+#define SVM_EXIT_TR_WRITE 0x6D
+/** RDTSC instruction. */
+#define SVM_EXIT_RDTSC 0x6E
+/** RDPMC instruction. */
+#define SVM_EXIT_RDPMC 0x6F
+/** PUSHF instruction. */
+#define SVM_EXIT_PUSHF 0x70
+/** POPF instruction. */
+#define SVM_EXIT_POPF 0x71
+/** CPUID instruction. */
+#define SVM_EXIT_CPUID 0x72
+/** RSM instruction. */
+#define SVM_EXIT_RSM 0x73
+/** IRET instruction. */
+#define SVM_EXIT_IRET 0x74
+/** software interrupt (INTn instructions). */
+#define SVM_EXIT_SWINT 0x75
+/** INVD instruction. */
+#define SVM_EXIT_INVD 0x76
+/** PAUSE instruction. */
+#define SVM_EXIT_PAUSE 0x77
+/** HLT instruction. */
+#define SVM_EXIT_HLT 0x78
+/** INVLPG instructions. */
+#define SVM_EXIT_INVLPG 0x79
+/** INVLPGA instruction. */
+#define SVM_EXIT_INVLPGA 0x7A
+/** IN or OUT accessing protected port (the EXITINFO1 field provides more information). */
+#define SVM_EXIT_IOIO 0x7B
+/** RDMSR or WRMSR access to protected MSR. */
+#define SVM_EXIT_MSR 0x7C
+/** task switch. */
+#define SVM_EXIT_TASK_SWITCH 0x7D
+/** FP legacy handling enabled, and processor is frozen in an x87/mmx instruction waiting for an interrupt. */
+#define SVM_EXIT_FERR_FREEZE 0x7E
+/** Shutdown. */
+#define SVM_EXIT_SHUTDOWN 0x7F
+/** VMRUN instruction. */
+#define SVM_EXIT_VMRUN 0x80
+/** VMMCALL instruction. */
+#define SVM_EXIT_VMMCALL 0x81
+/** VMLOAD instruction. */
+#define SVM_EXIT_VMLOAD 0x82
+/** VMSAVE instruction. */
+#define SVM_EXIT_VMSAVE 0x83
+/** STGI instruction. */
+#define SVM_EXIT_STGI 0x84
+/** CLGI instruction. */
+#define SVM_EXIT_CLGI 0x85
+/** SKINIT instruction. */
+#define SVM_EXIT_SKINIT 0x86
+/** RDTSCP instruction. */
+#define SVM_EXIT_RDTSCP 0x87
+/** ICEBP instruction. */
+#define SVM_EXIT_ICEBP 0x88
+/** WBINVD instruction. */
+#define SVM_EXIT_WBINVD 0x89
+/** MONITOR instruction. */
+#define SVM_EXIT_MONITOR 0x8A
+/** MWAIT instruction uncond. */
+#define SVM_EXIT_MWAIT_UNCOND 0x8B
+/** MWAIT instruction when armed. */
+#define SVM_EXIT_MWAIT_ARMED 0x8C
+/** Nested paging: host-level page fault occurred (EXITINFO1 contains fault errorcode; EXITINFO2 contains the guest physical address causing the fault). */
+#define SVM_EXIT_NPF 0x400
+
+/** @} */
+
+
+/** @name SVM_VMCB.u64ExitInfo2
+ * @{
+ */
+/** Set to 1 if the task switch was caused by an IRET; else cleared to 0. */
+#define SVM_EXIT2_TASK_SWITCH_IRET RT_BIT_64(36)
+/** Set to 1 if the task switch was caused by a far jump; else cleared to 0. */
+#define SVM_EXIT2_TASK_SWITCH_JMP RT_BIT_64(38)
+/** Set to 1 if the task switch has an error code; else cleared to 0. */
+#define SVM_EXIT2_TASK_SWITCH_HAS_ERROR_CODE RT_BIT_64(44)
+/** The value of EFLAGS.RF that would be saved in the outgoing TSS if the task switch were not intercepted. */
+#define SVM_EXIT2_TASK_SWITCH_EFLAGS_RF RT_BIT_64(48)
+/** @} */
+
+/** @name SVM_VMCB.ctrl.u32InterceptCtrl1
+ * @{
+ */
+/** 0 Intercept INTR (physical maskable interrupt). */
+#define SVM_CTRL1_INTERCEPT_INTR RT_BIT(0)
+/** 1 Intercept NMI. */
+#define SVM_CTRL1_INTERCEPT_NMI RT_BIT(1)
+/** 2 Intercept SMI. */
+#define SVM_CTRL1_INTERCEPT_SMI RT_BIT(2)
+/** 3 Intercept INIT. */
+#define SVM_CTRL1_INTERCEPT_INIT RT_BIT(3)
+/** 4 Intercept VINTR (virtual maskable interrupt). */
+#define SVM_CTRL1_INTERCEPT_VINTR RT_BIT(4)
+/** 5 Intercept CR0 writes that change bits other than CR0.TS or CR0.MP */
+#define SVM_CTRL1_INTERCEPT_CR0 RT_BIT(5)
+/** 6 Intercept reads of IDTR. */
+#define SVM_CTRL1_INTERCEPT_IDTR_READS RT_BIT(6)
+/** 7 Intercept reads of GDTR. */
+#define SVM_CTRL1_INTERCEPT_GDTR_READS RT_BIT(7)
+/** 8 Intercept reads of LDTR. */
+#define SVM_CTRL1_INTERCEPT_LDTR_READS RT_BIT(8)
+/** 9 Intercept reads of TR. */
+#define SVM_CTRL1_INTERCEPT_TR_READS RT_BIT(9)
+/** 10 Intercept writes of IDTR. */
+#define SVM_CTRL1_INTERCEPT_IDTR_WRITES RT_BIT(10)
+/** 11 Intercept writes of GDTR. */
+#define SVM_CTRL1_INTERCEPT_GDTR_WRITES RT_BIT(11)
+/** 12 Intercept writes of LDTR. */
+#define SVM_CTRL1_INTERCEPT_LDTR_WRITES RT_BIT(12)
+/** 13 Intercept writes of TR. */
+#define SVM_CTRL1_INTERCEPT_TR_WRITES RT_BIT(13)
+/** 14 Intercept RDTSC instruction. */
+#define SVM_CTRL1_INTERCEPT_RDTSC RT_BIT(14)
+/** 15 Intercept RDPMC instruction. */
+#define SVM_CTRL1_INTERCEPT_RDPMC RT_BIT(15)
+/** 16 Intercept PUSHF instruction. */
+#define SVM_CTRL1_INTERCEPT_PUSHF RT_BIT(16)
+/** 17 Intercept POPF instruction. */
+#define SVM_CTRL1_INTERCEPT_POPF RT_BIT(17)
+/** 18 Intercept CPUID instruction. */
+#define SVM_CTRL1_INTERCEPT_CPUID RT_BIT(18)
+/** 19 Intercept RSM instruction. */
+#define SVM_CTRL1_INTERCEPT_RSM RT_BIT(19)
+/** 20 Intercept IRET instruction. */
+#define SVM_CTRL1_INTERCEPT_IRET RT_BIT(20)
+/** 21 Intercept INTn instruction. */
+#define SVM_CTRL1_INTERCEPT_INTN RT_BIT(21)
+/** 22 Intercept INVD instruction. */
+#define SVM_CTRL1_INTERCEPT_INVD RT_BIT(22)
+/** 23 Intercept PAUSE instruction. */
+#define SVM_CTRL1_INTERCEPT_PAUSE RT_BIT(23)
+/** 24 Intercept HLT instruction. */
+#define SVM_CTRL1_INTERCEPT_HLT RT_BIT(24)
+/** 25 Intercept INVLPG instruction. */
+#define SVM_CTRL1_INTERCEPT_INVLPG RT_BIT(25)
+/** 26 Intercept INVLPGA instruction. */
+#define SVM_CTRL1_INTERCEPT_INVLPGA RT_BIT(26)
+/** 27 IOIO_PROT Intercept IN/OUT accesses to selected ports. */
+#define SVM_CTRL1_INTERCEPT_INOUT_BITMAP RT_BIT(27)
+/** 28 MSR_PROT Intercept RDMSR or WRMSR accesses to selected MSRs. */
+#define SVM_CTRL1_INTERCEPT_MSR_SHADOW RT_BIT(28)
+/** 29 Intercept task switches. */
+#define SVM_CTRL1_INTERCEPT_TASK_SWITCH RT_BIT(29)
+/** 30 FERR_FREEZE: intercept processor "freezing" during legacy FERR handling. */
+#define SVM_CTRL1_INTERCEPT_FERR_FREEZE RT_BIT(30)
+/** 31 Intercept shutdown events. */
+#define SVM_CTRL1_INTERCEPT_SHUTDOWN RT_BIT(31)
+/** @} */
+
+
+/** @name SVM_VMCB.ctrl.u32InterceptCtrl2
+ * @{
+ */
+/** 0 Intercept VMRUN instruction. */
+#define SVM_CTRL2_INTERCEPT_VMRUN RT_BIT(0)
+/** 1 Intercept VMMCALL instruction. */
+#define SVM_CTRL2_INTERCEPT_VMMCALL RT_BIT(1)
+/** 2 Intercept VMLOAD instruction. */
+#define SVM_CTRL2_INTERCEPT_VMLOAD RT_BIT(2)
+/** 3 Intercept VMSAVE instruction. */
+#define SVM_CTRL2_INTERCEPT_VMSAVE RT_BIT(3)
+/** 4 Intercept STGI instruction. */
+#define SVM_CTRL2_INTERCEPT_STGI RT_BIT(4)
+/** 5 Intercept CLGI instruction. */
+#define SVM_CTRL2_INTERCEPT_CLGI RT_BIT(5)
+/** 6 Intercept SKINIT instruction. */
+#define SVM_CTRL2_INTERCEPT_SKINIT RT_BIT(6)
+/** 7 Intercept RDTSCP instruction. */
+#define SVM_CTRL2_INTERCEPT_RDTSCP RT_BIT(7)
+/** 8 Intercept ICEBP instruction. */
+#define SVM_CTRL2_INTERCEPT_ICEBP RT_BIT(8)
+/** 9 Intercept WBINVD instruction. */
+#define SVM_CTRL2_INTERCEPT_WBINVD RT_BIT(9)
+/** 10 Intercept MONITOR instruction. */
+#define SVM_CTRL2_INTERCEPT_MONITOR RT_BIT(10)
+/** 11 Intercept MWAIT instruction unconditionally. */
+#define SVM_CTRL2_INTERCEPT_MWAIT_UNCOND RT_BIT(11)
+/** 12 Intercept MWAIT instruction when armed. */
+#define SVM_CTRL2_INTERCEPT_MWAIT_ARMED RT_BIT(12)
+/** 13 Intercept XSETBV instruction. */
+#define SVM_CTRL2_INTERCEPT_XSETBV RT_BIT(13)
+/** @} */
+
+/** @name SVM_VMCB.ctrl.u64NestedPaging
+ * @{
+ */
+#define SVM_NESTED_PAGING_ENABLE RT_BIT(0)
+/** @} */
+
+/** @name SVM_VMCB.ctrl.u64IntShadow
+ * @{
+ */
+#define SVM_INTERRUPT_SHADOW_ACTIVE RT_BIT(0)
+/** @} */
+
+
+/** @name SVM_INTCTRL.u3Type
+ * @{
+ */
+/** External or virtual interrupt. */
+#define SVM_EVENT_EXTERNAL_IRQ 0
+/** Non-maskable interrupt. */
+#define SVM_EVENT_NMI 2
+/** Exception; fault or trap. */
+#define SVM_EVENT_EXCEPTION 3
+/** Software interrupt. */
+#define SVM_EVENT_SOFTWARE_INT 4
+/** @} */
+
+
+/** @name SVM_VMCB.ctrl.TLBCtrl.n.u8TLBFlush
+ * @{
+ */
+/** Flush nothing. */
+#define SVM_TLB_FLUSH_NOTHING 0
+/** Flush entire TLB (host+guest entries) */
+#define SVM_TLB_FLUSH_ENTIRE 1
+/** Flush this guest's TLB entries (by ASID) */
+#define SVM_TLB_FLUSH_SINGLE_CONTEXT 3
+/** Flush this guest's non-global TLB entries (by ASID) */
+#define SVM_TLB_FLUSH_SINGLE_CONTEXT_RETAIN_GLOBALS 7
+/** @} */
+
+
+/**
+ * SVM Selector type; includes hidden parts.
+ */
+#pragma pack(1)
+typedef struct
+{
+ uint16_t u16Sel;
+ uint16_t u16Attr;
+ uint32_t u32Limit;
+ uint64_t u64Base; /**< Only lower 32 bits are implemented for CS, DS, ES & SS. */
+} SVMSEL;
+#pragma pack()
+
+/**
+ * SVM GDTR/IDTR type.
+ */
+#pragma pack(1)
+typedef struct
+{
+ uint16_t u16Reserved1;
+ uint16_t u16Reserved2;
+ uint32_t u32Limit; /**< Only lower 16 bits are implemented. */
+ uint64_t u64Base;
+} SVMGDTR;
+#pragma pack()
+
+typedef SVMGDTR SVMIDTR;
+
+/**
+ * SVM Event injection structure.
+ */
+#pragma pack(1)
+typedef union
+{
+ struct
+ {
+ uint32_t u8Vector : 8;
+ uint32_t u3Type : 3;
+ uint32_t u1ErrorCodeValid : 1;
+ uint32_t u19Reserved : 19;
+ uint32_t u1Valid : 1;
+ uint32_t u32ErrorCode : 32;
+ } n;
+ uint64_t au64[1];
+} SVM_EVENT;
+#pragma pack()
+
+
+/**
+ * SVM Interrupt control structure.
+ */
+#pragma pack(1)
+typedef union
+{
+ struct
+ {
+ uint32_t u8VTPR : 8;
+ uint32_t u1VIrqValid : 1;
+ uint32_t u7Reserved : 7;
+ uint32_t u4VIrqPriority : 4;
+ uint32_t u1IgnoreTPR : 1;
+ uint32_t u3Reserved : 3;
+ uint32_t u1VIrqMasking : 1;
+ uint32_t u7Reserved2 : 7;
+ uint32_t u8VIrqVector : 8;
+ uint32_t u24Reserved : 24;
+ } n;
+ uint64_t au64[1];
+} SVM_INTCTRL;
+#pragma pack()
+
+
+/**
+ * SVM TLB control structure.
+ */
+#pragma pack(1)
+typedef union
+{
+ struct
+ {
+ uint32_t u32ASID : 32;
+ uint32_t u8TLBFlush : 8;
+ uint32_t u24Reserved : 24;
+ } n;
+ uint64_t au64[1];
+} SVM_TLBCTRL;
+#pragma pack()
+
+
+/**
+ * SVM IOIO exit structure.
+ */
+#pragma pack(1)
+typedef union
+{
+ struct
+ {
+ uint32_t u1Type : 1; /**< 0 = out, 1 = in */
+ uint32_t u1Reserved : 1;
+ uint32_t u1STR : 1;
+ uint32_t u1REP : 1;
+ uint32_t u1OP8 : 1;
+ uint32_t u1OP16 : 1;
+ uint32_t u1OP32 : 1;
+ uint32_t u1ADDR16 : 1;
+ uint32_t u1ADDR32 : 1;
+ uint32_t u1ADDR64 : 1;
+ uint32_t u6Reserved : 6;
+ uint32_t u16Port : 16;
+ } n;
+ uint32_t au32[1];
+} SVM_IOIO_EXIT;
+#pragma pack()
+
+/**
+ * SVM nested paging structure.
+ */
+#pragma pack(1)
+typedef union
+{
+ struct
+ {
+ uint32_t u1NestedPaging : 1; /**< enabled/disabled */
+ } n;
+ uint64_t au64[1];
+} SVM_NPCTRL;
+#pragma pack()
+
+/**
+ * SVM VM Control Block. (VMCB)
+ */
+#pragma pack(1)
+typedef struct _SVM_VMCB
+{
+ /** Control Area. */
+ struct
+ {
+ /** Offset 0x00 - Intercept reads of CR0-15. */
+ uint16_t u16InterceptRdCRx;
+ /** Offset 0x02 - Intercept writes to CR0-15. */
+ uint16_t u16InterceptWrCRx;
+ /** Offset 0x04 - Intercept reads of DR0-15. */
+ uint16_t u16InterceptRdDRx;
+ /** Offset 0x06 - Intercept writes to DR0-15. */
+ uint16_t u16InterceptWrDRx;
+ /** Offset 0x08 - Intercept exception vectors 0-31. */
+ uint32_t u32InterceptException;
+ /** Offset 0x0C - Intercept control field 1. */
+ uint32_t u32InterceptCtrl1;
+ /** Offset 0x0C - Intercept control field 2. */
+ uint32_t u32InterceptCtrl2;
+ /** Offset 0x14-0x3F - Reserved. */
+ uint8_t u8Reserved[0x3e - 0x14];
+ /** Offset 0x3e - PAUSE intercept filter count. */
+ uint16_t u16PauseFilterCount;
+ /** Offset 0x40 - Physical address of IOPM. */
+ uint64_t u64IOPMPhysAddr;
+ /** Offset 0x48 - Physical address of MSRPM. */
+ uint64_t u64MSRPMPhysAddr;
+ /** Offset 0x50 - TSC Offset. */
+ uint64_t u64TSCOffset;
+ /** Offset 0x58 - TLB control field. */
+ SVM_TLBCTRL TLBCtrl;
+ /** Offset 0x60 - Interrupt control field. */
+ SVM_INTCTRL IntCtrl;
+ /** Offset 0x68 - Interrupt shadow. */
+ uint64_t u64IntShadow;
+ /** Offset 0x70 - Exit code. */
+ uint64_t u64ExitCode;
+ /** Offset 0x78 - Exit info 1. */
+ uint64_t u64ExitInfo1;
+ /** Offset 0x80 - Exit info 2. */
+ uint64_t u64ExitInfo2;
+ /** Offset 0x88 - Exit Interrupt info. */
+ SVM_EVENT ExitIntInfo;
+ /** Offset 0x90 - Nested Paging. */
+ SVM_NPCTRL NestedPaging;
+ /** Offset 0x98-0xA7 - Reserved. */
+ uint8_t u8Reserved2[0xA8-0x98];
+ /** Offset 0xA8 - Event injection. */
+ SVM_EVENT EventInject;
+ /** Offset 0xB0 - Host CR3 for nested paging. */
+ uint64_t u64NestedPagingCR3;
+ /** Offset 0xB8 - LBR Virtualization. */
+ uint64_t u64LBRVirt;
+ /** Offset 0xC0 - VMCB Clean Bits. */
+ uint64_t u64VMCBCleanBits;
+ /** Offset 0xC8 - Next sequential instruction pointer. */
+ uint64_t u64NextRIP;
+ /** Offset 0xD0 - Number of bytes fetched. */
+ uint8_t cbInstrFetched;
+ /** Offset 0xD1 - Number of bytes fetched. */
+ uint8_t abInstr[15];
+ } ctrl;
+
+ /** Offset 0xC0-0x3FF - Reserved. */
+ uint8_t u8Reserved3[0x400-0xE0];
+
+ /** State Save Area. Starts at offset 0x400. */
+ struct
+ {
+ /** Offset 0x400 - Guest ES register + hidden parts. */
+ SVMSEL ES;
+ /** Offset 0x410 - Guest CS register + hidden parts. */
+ SVMSEL CS;
+ /** Offset 0x420 - Guest SS register + hidden parts. */
+ SVMSEL SS;
+ /** Offset 0x430 - Guest DS register + hidden parts. */
+ SVMSEL DS;
+ /** Offset 0x440 - Guest FS register + hidden parts. */
+ SVMSEL FS;
+ /** Offset 0x450 - Guest GS register + hidden parts. */
+ SVMSEL GS;
+ /** Offset 0x460 - Guest GDTR register. */
+ SVMGDTR GDTR;
+ /** Offset 0x470 - Guest LDTR register + hidden parts. */
+ SVMSEL LDTR;
+ /** Offset 0x480 - Guest IDTR register. */
+ SVMIDTR IDTR;
+ /** Offset 0x490 - Guest TR register + hidden parts. */
+ SVMSEL TR;
+ /** Offset 0x4A0-0x4CA - Reserved. */
+ uint8_t u8Reserved4[0x4CB-0x4A0];
+ /** Offset 0x4CB - CPL. */
+ uint8_t u8CPL;
+ /** Offset 0x4CC-0x4CF - Reserved. */
+ uint8_t u8Reserved5[0x4D0-0x4CC];
+ /** Offset 0x4D0 - EFER. */
+ uint64_t u64EFER;
+ /** Offset 0x4D8-0x547 - Reserved. */
+ uint8_t u8Reserved6[0x548-0x4D8];
+ /** Offset 0x548 - CR4. */
+ uint64_t u64CR4;
+ /** Offset 0x550 - CR3. */
+ uint64_t u64CR3;
+ /** Offset 0x558 - CR0. */
+ uint64_t u64CR0;
+ /** Offset 0x560 - DR7. */
+ uint64_t u64DR7;
+ /** Offset 0x568 - DR6. */
+ uint64_t u64DR6;
+ /** Offset 0x570 - RFLAGS. */
+ uint64_t u64RFlags;
+ /** Offset 0x578 - RIP. */
+ uint64_t u64RIP;
+ /** Offset 0x580-0x5D7 - Reserved. */
+ uint8_t u8Reserved7[0x5D8-0x580];
+ /** Offset 0x5D8 - RSP. */
+ uint64_t u64RSP;
+ /** Offset 0x5E0-0x5F7 - Reserved. */
+ uint8_t u8Reserved8[0x5F8-0x5E0];
+ /** Offset 0x5F8 - RAX. */
+ uint64_t u64RAX;
+ /** Offset 0x600 - STAR. */
+ uint64_t u64STAR;
+ /** Offset 0x608 - LSTAR. */
+ uint64_t u64LSTAR;
+ /** Offset 0x610 - CSTAR. */
+ uint64_t u64CSTAR;
+ /** Offset 0x618 - SFMASK. */
+ uint64_t u64SFMASK;
+ /** Offset 0x620 - KernelGSBase. */
+ uint64_t u64KernelGSBase;
+ /** Offset 0x628 - SYSENTER_CS. */
+ uint64_t u64SysEnterCS;
+ /** Offset 0x630 - SYSENTER_ESP. */
+ uint64_t u64SysEnterESP;
+ /** Offset 0x638 - SYSENTER_EIP. */
+ uint64_t u64SysEnterEIP;
+ /** Offset 0x640 - CR2. */
+ uint64_t u64CR2;
+ /** Offset 0x648-0x667 - Reserved. */
+ uint8_t u8Reserved9[0x668-0x648];
+ /** Offset 0x668 - G_PAT. */
+ uint64_t u64GPAT;
+ /** Offset 0x670 - DBGCTL. */
+ uint64_t u64DBGCTL;
+ /** Offset 0x678 - BR_FROM. */
+ uint64_t u64BR_FROM;
+ /** Offset 0x680 - BR_TO. */
+ uint64_t u64BR_TO;
+ /** Offset 0x688 - LASTEXCPFROM. */
+ uint64_t u64LASTEXCPFROM;
+ /** Offset 0x690 - LASTEXCPTO. */
+ uint64_t u64LASTEXCPTO;
+ } guest;
+
+ /** Offset 0x698-0xFFF- Reserved. */
+ uint8_t u8Reserved10[0x1000-0x698];
+} SVM_VMCB;
+#pragma pack()
+AssertCompileSize(SVM_VMCB, 0x1000);
+AssertCompileMemberOffset(SVM_VMCB, ctrl.u16InterceptRdCRx, 0x000);
+AssertCompileMemberOffset(SVM_VMCB, ctrl.u16PauseFilterCount,0x03e);
+AssertCompileMemberOffset(SVM_VMCB, ctrl.TLBCtrl, 0x058);
+AssertCompileMemberOffset(SVM_VMCB, ctrl.ExitIntInfo, 0x088);
+AssertCompileMemberOffset(SVM_VMCB, ctrl.EventInject, 0x0A8);
+AssertCompileMemberOffset(SVM_VMCB, ctrl.abInstr, 0x0D1);
+AssertCompileMemberOffset(SVM_VMCB, guest, 0x400);
+AssertCompileMemberOffset(SVM_VMCB, guest.ES, 0x400);
+AssertCompileMemberOffset(SVM_VMCB, guest.u8Reserved4, 0x4A0);
+AssertCompileMemberOffset(SVM_VMCB, guest.u8CPL, 0x4CB);
+AssertCompileMemberOffset(SVM_VMCB, guest.u8Reserved6, 0x4D8);
+AssertCompileMemberOffset(SVM_VMCB, guest.u8Reserved7, 0x580);
+AssertCompileMemberOffset(SVM_VMCB, guest.u8Reserved9, 0x648);
+AssertCompileMemberOffset(SVM_VMCB, guest.u64GPAT, 0x668);
+AssertCompileMemberOffset(SVM_VMCB, guest.u64LASTEXCPTO, 0x690);
+AssertCompileMemberOffset(SVM_VMCB, u8Reserved10, 0x698);
+
+#ifdef IN_RING0
+VMMR0DECL(int) SVMR0InvalidatePage(PVM pVM, PVMCPU pVCpu, RTGCPTR GCVirt);
+#endif /* IN_RING0 */
+
+/** @} */
+
+#endif
+
diff --git a/include/VBox/vmm/hwacc_vmx.h b/include/VBox/vmm/hwacc_vmx.h
new file mode 100644
index 00000000..a96f587e
--- /dev/null
+++ b/include/VBox/vmm/hwacc_vmx.h
@@ -0,0 +1,1708 @@
+/** @file
+ * HWACCM - VMX Structures and Definitions. (VMM)
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_vmx_h
+#define ___VBox_vmm_vmx_h
+
+#include <VBox/types.h>
+#include <VBox/err.h>
+#include <iprt/x86.h>
+#include <iprt/assert.h>
+
+/** @defgroup grp_vmx vmx Types and Definitions
+ * @ingroup grp_hwaccm
+ * @{
+ */
+
+/** @name VMX EPT paging structures
+ * @{
+ */
+
+/**
+ * Number of page table entries in the EPT. (PDPTE/PDE/PTE)
+ */
+#define EPT_PG_ENTRIES X86_PG_PAE_ENTRIES
+
+/**
+ * EPT Page Directory Pointer Entry. Bit view.
+ * @todo uint64_t isn't safe for bitfields (gcc pedantic warnings, and IIRC,
+ * this did cause trouble with one compiler/version).
+ */
+#pragma pack(1)
+typedef struct EPTPML4EBITS
+{
+ /** Present bit. */
+ uint64_t u1Present : 1;
+ /** Writable bit. */
+ uint64_t u1Write : 1;
+ /** Executable bit. */
+ uint64_t u1Execute : 1;
+ /** Reserved (must be 0). */
+ uint64_t u5Reserved : 5;
+ /** Available for software. */
+ uint64_t u4Available : 4;
+ /** Physical address of the next level (PD). Restricted by maximum physical address width of the cpu. */
+ uint64_t u40PhysAddr : 40;
+ /** Availabe for software. */
+ uint64_t u12Available : 12;
+} EPTPML4EBITS;
+#pragma pack()
+AssertCompileSize(EPTPML4EBITS, 8);
+
+/** Bits 12-51 - - EPT - Physical Page number of the next level. */
+#define EPT_PML4E_PG_MASK X86_PML4E_PG_MASK
+/** The page shift to get the PML4 index. */
+#define EPT_PML4_SHIFT X86_PML4_SHIFT
+/** The PML4 index mask (apply to a shifted page address). */
+#define EPT_PML4_MASK X86_PML4_MASK
+
+/**
+ * EPT PML4E.
+ */
+#pragma pack(1)
+typedef union EPTPML4E
+{
+ /** Normal view. */
+ EPTPML4EBITS n;
+ /** Unsigned integer view. */
+ X86PGPAEUINT u;
+ /** 64 bit unsigned integer view. */
+ uint64_t au64[1];
+ /** 32 bit unsigned integer view. */
+ uint32_t au32[2];
+} EPTPML4E;
+#pragma pack()
+/** Pointer to a PML4 table entry. */
+typedef EPTPML4E *PEPTPML4E;
+/** Pointer to a const PML4 table entry. */
+typedef const EPTPML4E *PCEPTPML4E;
+AssertCompileSize(EPTPML4E, 8);
+
+/**
+ * EPT PML4 Table.
+ */
+#pragma pack(1)
+typedef struct EPTPML4
+{
+ EPTPML4E a[EPT_PG_ENTRIES];
+} EPTPML4;
+#pragma pack()
+/** Pointer to an EPT PML4 Table. */
+typedef EPTPML4 *PEPTPML4;
+/** Pointer to a const EPT PML4 Table. */
+typedef const EPTPML4 *PCEPTPML4;
+
+/**
+ * EPT Page Directory Pointer Entry. Bit view.
+ */
+#pragma pack(1)
+typedef struct EPTPDPTEBITS
+{
+ /** Present bit. */
+ uint64_t u1Present : 1;
+ /** Writable bit. */
+ uint64_t u1Write : 1;
+ /** Executable bit. */
+ uint64_t u1Execute : 1;
+ /** Reserved (must be 0). */
+ uint64_t u5Reserved : 5;
+ /** Available for software. */
+ uint64_t u4Available : 4;
+ /** Physical address of the next level (PD). Restricted by maximum physical address width of the cpu. */
+ uint64_t u40PhysAddr : 40;
+ /** Availabe for software. */
+ uint64_t u12Available : 12;
+} EPTPDPTEBITS;
+#pragma pack()
+AssertCompileSize(EPTPDPTEBITS, 8);
+
+/** Bits 12-51 - - EPT - Physical Page number of the next level. */
+#define EPT_PDPTE_PG_MASK X86_PDPE_PG_MASK
+/** The page shift to get the PDPT index. */
+#define EPT_PDPT_SHIFT X86_PDPT_SHIFT
+/** The PDPT index mask (apply to a shifted page address). */
+#define EPT_PDPT_MASK X86_PDPT_MASK_AMD64
+
+/**
+ * EPT Page Directory Pointer.
+ */
+#pragma pack(1)
+typedef union EPTPDPTE
+{
+ /** Normal view. */
+ EPTPDPTEBITS n;
+ /** Unsigned integer view. */
+ X86PGPAEUINT u;
+ /** 64 bit unsigned integer view. */
+ uint64_t au64[1];
+ /** 32 bit unsigned integer view. */
+ uint32_t au32[2];
+} EPTPDPTE;
+#pragma pack()
+/** Pointer to an EPT Page Directory Pointer Entry. */
+typedef EPTPDPTE *PEPTPDPTE;
+/** Pointer to a const EPT Page Directory Pointer Entry. */
+typedef const EPTPDPTE *PCEPTPDPTE;
+AssertCompileSize(EPTPDPTE, 8);
+
+/**
+ * EPT Page Directory Pointer Table.
+ */
+#pragma pack(1)
+typedef struct EPTPDPT
+{
+ EPTPDPTE a[EPT_PG_ENTRIES];
+} EPTPDPT;
+#pragma pack()
+/** Pointer to an EPT Page Directory Pointer Table. */
+typedef EPTPDPT *PEPTPDPT;
+/** Pointer to a const EPT Page Directory Pointer Table. */
+typedef const EPTPDPT *PCEPTPDPT;
+
+
+/**
+ * EPT Page Directory Table Entry. Bit view.
+ */
+#pragma pack(1)
+typedef struct EPTPDEBITS
+{
+ /** Present bit. */
+ uint64_t u1Present : 1;
+ /** Writable bit. */
+ uint64_t u1Write : 1;
+ /** Executable bit. */
+ uint64_t u1Execute : 1;
+ /** Reserved (must be 0). */
+ uint64_t u4Reserved : 4;
+ /** Big page (must be 0 here). */
+ uint64_t u1Size : 1;
+ /** Available for software. */
+ uint64_t u4Available : 4;
+ /** Physical address of page table. Restricted by maximum physical address width of the cpu. */
+ uint64_t u40PhysAddr : 40;
+ /** Availabe for software. */
+ uint64_t u12Available : 12;
+} EPTPDEBITS;
+#pragma pack()
+AssertCompileSize(EPTPDEBITS, 8);
+
+/** Bits 12-51 - - EPT - Physical Page number of the next level. */
+#define EPT_PDE_PG_MASK X86_PDE_PAE_PG_MASK
+/** The page shift to get the PD index. */
+#define EPT_PD_SHIFT X86_PD_PAE_SHIFT
+/** The PD index mask (apply to a shifted page address). */
+#define EPT_PD_MASK X86_PD_PAE_MASK
+
+/**
+ * EPT 2MB Page Directory Table Entry. Bit view.
+ */
+#pragma pack(1)
+typedef struct EPTPDE2MBITS
+{
+ /** Present bit. */
+ uint64_t u1Present : 1;
+ /** Writable bit. */
+ uint64_t u1Write : 1;
+ /** Executable bit. */
+ uint64_t u1Execute : 1;
+ /** EPT Table Memory Type. MBZ for non-leaf nodes. */
+ uint64_t u3EMT : 3;
+ /** Ignore PAT memory type */
+ uint64_t u1IgnorePAT : 1;
+ /** Big page (must be 1 here). */
+ uint64_t u1Size : 1;
+ /** Available for software. */
+ uint64_t u4Available : 4;
+ /** Reserved (must be 0). */
+ uint64_t u9Reserved : 9;
+ /** Physical address of the 2MB page. Restricted by maximum physical address width of the cpu. */
+ uint64_t u31PhysAddr : 31;
+ /** Availabe for software. */
+ uint64_t u12Available : 12;
+} EPTPDE2MBITS;
+#pragma pack()
+AssertCompileSize(EPTPDE2MBITS, 8);
+
+/** Bits 21-51 - - EPT - Physical Page number of the next level. */
+#define EPT_PDE2M_PG_MASK X86_PDE2M_PAE_PG_MASK
+
+/**
+ * EPT Page Directory Table Entry.
+ */
+#pragma pack(1)
+typedef union EPTPDE
+{
+ /** Normal view. */
+ EPTPDEBITS n;
+ /** 2MB view (big). */
+ EPTPDE2MBITS b;
+ /** Unsigned integer view. */
+ X86PGPAEUINT u;
+ /** 64 bit unsigned integer view. */
+ uint64_t au64[1];
+ /** 32 bit unsigned integer view. */
+ uint32_t au32[2];
+} EPTPDE;
+#pragma pack()
+/** Pointer to an EPT Page Directory Table Entry. */
+typedef EPTPDE *PEPTPDE;
+/** Pointer to a const EPT Page Directory Table Entry. */
+typedef const EPTPDE *PCEPTPDE;
+AssertCompileSize(EPTPDE, 8);
+
+/**
+ * EPT Page Directory Table.
+ */
+#pragma pack(1)
+typedef struct EPTPD
+{
+ EPTPDE a[EPT_PG_ENTRIES];
+} EPTPD;
+#pragma pack()
+/** Pointer to an EPT Page Directory Table. */
+typedef EPTPD *PEPTPD;
+/** Pointer to a const EPT Page Directory Table. */
+typedef const EPTPD *PCEPTPD;
+
+
+/**
+ * EPT Page Table Entry. Bit view.
+ */
+#pragma pack(1)
+typedef struct EPTPTEBITS
+{
+ /** 0 - Present bit.
+ * @remark This is a convenience "misnomer". The bit actually indicates
+ * read access and the CPU will consider an entry with any of the
+ * first three bits set as present. Since all our valid entries
+ * will have this bit set, it can be used as a present indicator
+ * and allow some code sharing. */
+ uint64_t u1Present : 1;
+ /** 1 - Writable bit. */
+ uint64_t u1Write : 1;
+ /** 2 - Executable bit. */
+ uint64_t u1Execute : 1;
+ /** 5:3 - EPT Memory Type. MBZ for non-leaf nodes. */
+ uint64_t u3EMT : 3;
+ /** 6 - Ignore PAT memory type */
+ uint64_t u1IgnorePAT : 1;
+ /** 11:7 - Available for software. */
+ uint64_t u5Available : 5;
+ /** 51:12 - Physical address of page. Restricted by maximum physical
+ * address width of the cpu. */
+ uint64_t u40PhysAddr : 40;
+ /** 63:52 - Available for software. */
+ uint64_t u12Available : 12;
+} EPTPTEBITS;
+#pragma pack()
+AssertCompileSize(EPTPTEBITS, 8);
+
+/** Bits 12-51 - - EPT - Physical Page number of the next level. */
+#define EPT_PTE_PG_MASK X86_PTE_PAE_PG_MASK
+/** The page shift to get the EPT PTE index. */
+#define EPT_PT_SHIFT X86_PT_PAE_SHIFT
+/** The EPT PT index mask (apply to a shifted page address). */
+#define EPT_PT_MASK X86_PT_PAE_MASK
+
+/**
+ * EPT Page Table Entry.
+ */
+#pragma pack(1)
+typedef union EPTPTE
+{
+ /** Normal view. */
+ EPTPTEBITS n;
+ /** Unsigned integer view. */
+ X86PGPAEUINT u;
+ /** 64 bit unsigned integer view. */
+ uint64_t au64[1];
+ /** 32 bit unsigned integer view. */
+ uint32_t au32[2];
+} EPTPTE;
+#pragma pack()
+/** Pointer to an EPT Page Directory Table Entry. */
+typedef EPTPTE *PEPTPTE;
+/** Pointer to a const EPT Page Directory Table Entry. */
+typedef const EPTPTE *PCEPTPTE;
+AssertCompileSize(EPTPTE, 8);
+
+/**
+ * EPT Page Table.
+ */
+#pragma pack(1)
+typedef struct EPTPT
+{
+ EPTPTE a[EPT_PG_ENTRIES];
+} EPTPT;
+#pragma pack()
+/** Pointer to an extended page table. */
+typedef EPTPT *PEPTPT;
+/** Pointer to a const extended table. */
+typedef const EPTPT *PCEPTPT;
+
+/**
+ * VPID flush types.
+ */
+typedef enum
+{
+ /** Invalidate a specific page. */
+ VMX_FLUSH_VPID_INDIV_ADDR = 0,
+ /** Invalidate one context (specific VPID). */
+ VMX_FLUSH_VPID_SINGLE_CONTEXT = 1,
+ /** Invalidate all contexts (all VPIDs). */
+ VMX_FLUSH_VPID_ALL_CONTEXTS = 2,
+ /** Invalidate a single VPID context retaining global mappings. */
+ VMX_FLUSH_VPID_SINGLE_CONTEXT_RETAIN_GLOBALS = 3,
+ /** Unsupported by VirtualBox. */
+ VMX_FLUSH_VPID_NOT_SUPPORTED = 0xbad,
+ /** Unsupported by CPU. */
+ VMX_FLUSH_VPID_NONE = 0xb00,
+ /** 32bit hackishness. */
+ VMX_FLUSH_VPID_32BIT_HACK = 0x7fffffff
+} VMX_FLUSH_VPID;
+
+/**
+ * EPT flush types.
+ */
+typedef enum
+{
+ /** Invalidate one context (specific EPT). */
+ VMX_FLUSH_EPT_SINGLE_CONTEXT = 1,
+ /* Invalidate all contexts (all EPTs) */
+ VMX_FLUSH_EPT_ALL_CONTEXTS = 2,
+ /** Unsupported by VirtualBox. */
+ VMX_FLUSH_EPT_NOT_SUPPORTED = 0xbad,
+ /** Unsupported by CPU. */
+ VMX_FLUSH_EPT_NONE = 0xb00,
+ /** 32bit hackishness. */
+ VMX_FLUSH_EPT_32BIT_HACK = 0x7fffffff
+} VMX_FLUSH_EPT;
+/** @} */
+
+/** @name MSR load/store elements
+ * @{
+ */
+#pragma pack(1)
+typedef struct
+{
+ uint32_t u32IndexMSR;
+ uint32_t u32Reserved;
+ uint64_t u64Value;
+} VMXMSR;
+#pragma pack()
+/** Pointer to an MSR load/store element. */
+typedef VMXMSR *PVMXMSR;
+/** Pointer to a const MSR load/store element. */
+typedef const VMXMSR *PCVMXMSR;
+
+/** @} */
+
+
+/** @name VT-x capability qword
+ * @{
+ */
+#pragma pack(1)
+typedef union
+{
+ struct
+ {
+ uint32_t disallowed0;
+ uint32_t allowed1;
+ } n;
+ uint64_t u;
+} VMX_CAPABILITY;
+#pragma pack()
+/** @} */
+
+/** @name VMX Basic Exit Reasons.
+ * @{
+ */
+/** And-mask for setting reserved bits to zero */
+#define VMX_EFLAGS_RESERVED_0 (~0xffc08028)
+/** Or-mask for setting reserved bits to 1 */
+#define VMX_EFLAGS_RESERVED_1 0x00000002
+/** @} */
+
+/** @name VMX Basic Exit Reasons.
+ * @{
+ */
+/** -1 Invalid exit code */
+#define VMX_EXIT_INVALID -1
+/** 0 Exception or non-maskable interrupt (NMI). */
+#define VMX_EXIT_EXCEPTION 0
+/** 1 External interrupt. */
+#define VMX_EXIT_EXTERNAL_IRQ 1
+/** 2 Triple fault. */
+#define VMX_EXIT_TRIPLE_FAULT 2
+/** 3 INIT signal. */
+#define VMX_EXIT_INIT_SIGNAL 3
+/** 4 Start-up IPI (SIPI). */
+#define VMX_EXIT_SIPI 4
+/** 5 I/O system-management interrupt (SMI). */
+#define VMX_EXIT_IO_SMI_IRQ 5
+/** 6 Other SMI. */
+#define VMX_EXIT_SMI_IRQ 6
+/** 7 Interrupt window. */
+#define VMX_EXIT_IRQ_WINDOW 7
+/** 9 Task switch. */
+#define VMX_EXIT_TASK_SWITCH 9
+/** 10 Guest software attempted to execute CPUID. */
+#define VMX_EXIT_CPUID 10
+/** 12 Guest software attempted to execute HLT. */
+#define VMX_EXIT_HLT 12
+/** 13 Guest software attempted to execute INVD. */
+#define VMX_EXIT_INVD 13
+/** 14 Guest software attempted to execute INVLPG. */
+#define VMX_EXIT_INVLPG 14
+/** 15 Guest software attempted to execute RDPMC. */
+#define VMX_EXIT_RDPMC 15
+/** 16 Guest software attempted to execute RDTSC. */
+#define VMX_EXIT_RDTSC 16
+/** 17 Guest software attempted to execute RSM in SMM. */
+#define VMX_EXIT_RSM 17
+/** 18 Guest software executed VMCALL. */
+#define VMX_EXIT_VMCALL 18
+/** 19 Guest software executed VMCLEAR. */
+#define VMX_EXIT_VMCLEAR 19
+/** 20 Guest software executed VMLAUNCH. */
+#define VMX_EXIT_VMLAUNCH 20
+/** 21 Guest software executed VMPTRLD. */
+#define VMX_EXIT_VMPTRLD 21
+/** 22 Guest software executed VMPTRST. */
+#define VMX_EXIT_VMPTRST 22
+/** 23 Guest software executed VMREAD. */
+#define VMX_EXIT_VMREAD 23
+/** 24 Guest software executed VMRESUME. */
+#define VMX_EXIT_VMRESUME 24
+/** 25 Guest software executed VMWRITE. */
+#define VMX_EXIT_VMWRITE 25
+/** 26 Guest software executed VMXOFF. */
+#define VMX_EXIT_VMXOFF 26
+/** 27 Guest software executed VMXON. */
+#define VMX_EXIT_VMXON 27
+/** 28 Control-register accesses. */
+#define VMX_EXIT_CRX_MOVE 28
+/** 29 Debug-register accesses. */
+#define VMX_EXIT_DRX_MOVE 29
+/** 30 I/O instruction. */
+#define VMX_EXIT_PORT_IO 30
+/** 31 RDMSR. Guest software attempted to execute RDMSR. */
+#define VMX_EXIT_RDMSR 31
+/** 32 WRMSR. Guest software attempted to execute WRMSR. */
+#define VMX_EXIT_WRMSR 32
+/** 33 VM-entry failure due to invalid guest state. */
+#define VMX_EXIT_ERR_INVALID_GUEST_STATE 33
+/** 34 VM-entry failure due to MSR loading. */
+#define VMX_EXIT_ERR_MSR_LOAD 34
+/** 36 Guest software executed MWAIT. */
+#define VMX_EXIT_MWAIT 36
+/** 37 VM exit due to monitor trap flag. */
+#define VMX_EXIT_MTF 37
+/** 39 Guest software attempted to execute MONITOR. */
+#define VMX_EXIT_MONITOR 39
+/** 40 Guest software attempted to execute PAUSE. */
+#define VMX_EXIT_PAUSE 40
+/** 41 VM-entry failure due to machine-check. */
+#define VMX_EXIT_ERR_MACHINE_CHECK 41
+/** 43 TPR below threshold. Guest software executed MOV to CR8. */
+#define VMX_EXIT_TPR 43
+/** 44 APIC access. Guest software attempted to access memory at a physical address on the APIC-access page. */
+#define VMX_EXIT_APIC_ACCESS 44
+/** 46 Access to GDTR or IDTR. Guest software attempted to execute LGDT, LIDT, SGDT, or SIDT. */
+#define VMX_EXIT_XDTR_ACCESS 46
+/** 47 Access to LDTR or TR. Guest software attempted to execute LLDT, LTR, SLDT, or STR. */
+#define VMX_EXIT_TR_ACCESS 47
+/** 48 EPT violation. An attempt to access memory with a guest-physical address was disallowed by the configuration of the EPT paging structures. */
+#define VMX_EXIT_EPT_VIOLATION 48
+/** 49 EPT misconfiguration. An attempt to access memory with a guest-physical address encountered a misconfigured EPT paging-structure entry. */
+#define VMX_EXIT_EPT_MISCONFIG 49
+/** 50 INVEPT. Guest software attempted to execute INVEPT. */
+#define VMX_EXIT_INVEPT 50
+/** 51 RDTSCP. Guest software attempted to execute RDTSCP. */
+#define VMX_EXIT_RDTSCP 51
+/** 52 VMX-preemption timer expired. The preemption timer counted down to zero. */
+#define VMX_EXIT_PREEMPTION_TIMER 52
+/** 53 INVVPID. Guest software attempted to execute INVVPID. */
+#define VMX_EXIT_INVVPID 53
+/** 54 WBINVD. Guest software attempted to execute WBINVD. */
+#define VMX_EXIT_WBINVD 54
+/** 55 XSETBV. Guest software attempted to execute XSETBV. */
+#define VMX_EXIT_XSETBV 55
+/** @} */
+
+
+/** @name VM Instruction Errors
+ * @{
+ */
+/** 1 VMCALL executed in VMX root operation. */
+#define VMX_ERROR_VMCALL 1
+/** 2 VMCLEAR with invalid physical address. */
+#define VMX_ERROR_VMCLEAR_INVALID_PHYS_ADDR 2
+/** 3 VMCLEAR with VMXON pointer. */
+#define VMX_ERROR_VMCLEAR_INVALID_VMXON_PTR 3
+/** 4 VMLAUNCH with non-clear VMCS. */
+#define VMX_ERROR_VMLAUCH_NON_CLEAR_VMCS 4
+/** 5 VMRESUME with non-launched VMCS. */
+#define VMX_ERROR_VMRESUME_NON_LAUNCHED_VMCS 5
+/** 6 VMRESUME with a corrupted VMCS (indicates corruption of the current VMCS). */
+#define VMX_ERROR_VMRESUME_CORRUPTED_VMCS 6
+/** 7 VM entry with invalid control field(s). */
+#define VMX_ERROR_VMENTRY_INVALID_CONTROL_FIELDS 7
+/** 8 VM entry with invalid host-state field(s). */
+#define VMX_ERROR_VMENTRY_INVALID_HOST_STATE 8
+/** 9 VMPTRLD with invalid physical address. */
+#define VMX_ERROR_VMPTRLD_INVALID_PHYS_ADDR 9
+/** 10 VMPTRLD with VMXON pointer. */
+#define VMX_ERROR_VMPTRLD_VMXON_PTR 10
+/** 11 VMPTRLD with incorrect VMCS revision identifier. */
+#define VMX_ERROR_VMPTRLD_WRONG_VMCS_REVISION 11
+/** 12 VMREAD/VMWRITE from/to unsupported VMCS component. */
+#define VMX_ERROR_VMREAD_INVALID_COMPONENT 12
+#define VMX_ERROR_VMWRITE_INVALID_COMPONENT VMX_ERROR_VMREAD_INVALID_COMPONENT
+/** 13 VMWRITE to read-only VMCS component. */
+#define VMX_ERROR_VMWRITE_READONLY_COMPONENT 13
+/** 15 VMXON executed in VMX root operation. */
+#define VMX_ERROR_VMXON_IN_VMX_ROOT_OP 15
+/** 16 VM entry with invalid executive-VMCS pointer. */
+#define VMX_ERROR_VMENTRY_INVALID_VMCS_EXEC_PTR 16
+/** 17 VM entry with non-launched executive VMCS. */
+#define VMX_ERROR_VMENTRY_NON_LAUNCHED_EXEC_VMCS 17
+/** 18 VM entry with executive-VMCS pointer not VMXON pointer. */
+#define VMX_ERROR_VMENTRY_EXEC_VMCS_PTR 18
+/** 19 VMCALL with non-clear VMCS. */
+#define VMX_ERROR_VMCALL_NON_CLEAR_VMCS 19
+/** 20 VMCALL with invalid VM-exit control fields. */
+#define VMX_ERROR_VMCALL_INVALID_VMEXIT_FIELDS 20
+/** 22 VMCALL with incorrect MSEG revision identifier. */
+#define VMX_ERROR_VMCALL_INVALID_MSEG_REVISION 22
+/** 23 VMXOFF under dual-monitor treatment of SMIs and SMM. */
+#define VMX_ERROR_VMXOFF_DUAL_MONITOR 23
+/** 24 VMCALL with invalid SMM-monitor features. */
+#define VMX_ERROR_VMCALL_INVALID_SMM_MONITOR 24
+/** 25 VM entry with invalid VM-execution control fields in executive VMCS. */
+#define VMX_ERROR_VMENTRY_INVALID_VM_EXEC_CTRL 25
+/** 26 VM entry with events blocked by MOV SS. */
+#define VMX_ERROR_VMENTRY_MOV_SS 26
+/** 26 Invalid operand to INVEPT/INVVPID. */
+#define VMX_ERROR_INVEPTVPID_INVALID_OPERAND 28
+
+/** @} */
+
+
+/** @name VMX MSRs - Basic VMX information.
+ * @{
+ */
+/** VMCS revision identifier used by the processor. */
+#define MSR_IA32_VMX_BASIC_INFO_VMCS_ID(a) (a & 0x7FFFFFFF)
+/** Size of the VMCS. */
+#define MSR_IA32_VMX_BASIC_INFO_VMCS_SIZE(a) (((a) >> 32) & 0xFFF)
+/** Width of physical address used for the VMCS.
+ * 0 -> limited to the available amount of physical ram
+ * 1 -> within the first 4 GB
+ */
+#define MSR_IA32_VMX_BASIC_INFO_VMCS_PHYS_WIDTH(a) (((a) >> 48) & 1)
+/** Whether the processor supports the dual-monitor treatment of system-management interrupts and system-management code. (always 1) */
+#define MSR_IA32_VMX_BASIC_INFO_VMCS_DUAL_MON(a) (((a) >> 49) & 1)
+/** Memory type that must be used for the VMCS. */
+#define MSR_IA32_VMX_BASIC_INFO_VMCS_MEM_TYPE(a) (((a) >> 50) & 0xF)
+/** @} */
+
+
+/** @name VMX MSRs - Misc VMX info.
+ * @{
+ */
+/** Relationship between the preemption timer and tsc; count down every time bit x of the tsc changes. */
+#define MSR_IA32_VMX_MISC_PREEMPT_TSC_BIT(a) ((a) & 0x1f)
+/** Activity states supported by the implementation. */
+#define MSR_IA32_VMX_MISC_ACTIVITY_STATES(a) (((a) >> 6) & 0x7)
+/** Number of CR3 target values supported by the processor. (0-256) */
+#define MSR_IA32_VMX_MISC_CR3_TARGET(a) (((a) >> 16) & 0x1FF)
+/** Maximum nr of MSRs in the VMCS. (N+1)*512. */
+#define MSR_IA32_VMX_MISC_MAX_MSR(a) (((((a) >> 25) & 0x7) + 1) * 512)
+/** MSEG revision identifier used by the processor. */
+#define MSR_IA32_VMX_MISC_MSEG_ID(a) ((a) >> 32)
+/** @} */
+
+
+/** @name VMX MSRs - VMCS enumeration field info
+ * @{
+ */
+/** Highest field index. */
+#define MSR_IA32_VMX_VMCS_ENUM_HIGHEST_INDEX(a) (((a) >> 1) & 0x1FF)
+
+/** @} */
+
+
+/** @name MSR_IA32_VMX_EPT_CAPS; EPT capabilities MSR
+ * @{
+ */
+#define MSR_IA32_VMX_EPT_CAPS_RWX_X_ONLY RT_BIT_64(0)
+#define MSR_IA32_VMX_EPT_CAPS_RWX_W_ONLY RT_BIT_64(1)
+#define MSR_IA32_VMX_EPT_CAPS_RWX_WX_ONLY RT_BIT_64(2)
+#define MSR_IA32_VMX_EPT_CAPS_GAW_21_BITS RT_BIT_64(3)
+#define MSR_IA32_VMX_EPT_CAPS_GAW_30_BITS RT_BIT_64(4)
+#define MSR_IA32_VMX_EPT_CAPS_GAW_39_BITS RT_BIT_64(5)
+#define MSR_IA32_VMX_EPT_CAPS_GAW_48_BITS RT_BIT_64(6)
+#define MSR_IA32_VMX_EPT_CAPS_GAW_57_BITS RT_BIT_64(7)
+#define MSR_IA32_VMX_EPT_CAPS_EMT_UC RT_BIT_64(8)
+#define MSR_IA32_VMX_EPT_CAPS_EMT_WC RT_BIT_64(9)
+#define MSR_IA32_VMX_EPT_CAPS_EMT_WT RT_BIT_64(12)
+#define MSR_IA32_VMX_EPT_CAPS_EMT_WP RT_BIT_64(13)
+#define MSR_IA32_VMX_EPT_CAPS_EMT_WB RT_BIT_64(14)
+#define MSR_IA32_VMX_EPT_CAPS_SP_21_BITS RT_BIT_64(16)
+#define MSR_IA32_VMX_EPT_CAPS_SP_30_BITS RT_BIT_64(17)
+#define MSR_IA32_VMX_EPT_CAPS_SP_39_BITS RT_BIT_64(18)
+#define MSR_IA32_VMX_EPT_CAPS_SP_48_BITS RT_BIT_64(19)
+#define MSR_IA32_VMX_EPT_CAPS_INVEPT RT_BIT_64(20)
+#define MSR_IA32_VMX_EPT_CAPS_INVEPT_CAPS_SINGLE_CONTEXT RT_BIT_64(25)
+#define MSR_IA32_VMX_EPT_CAPS_INVEPT_CAPS_ALL_CONTEXTS RT_BIT_64(26)
+#define MSR_IA32_VMX_EPT_CAPS_INVVPID RT_BIT_64(32)
+#define MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_INDIV_ADDR RT_BIT_64(40)
+#define MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_SINGLE_CONTEXT RT_BIT_64(41)
+#define MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_ALL_CONTEXTS RT_BIT_64(42)
+#define MSR_IA32_VMX_EPT_CAPS_INVVPID_CAPS_SINGLE_CONTEXT_RETAIN_GLOBALS RT_BIT_64(43)
+
+/** @} */
+
+/** @name Extended Page Table Pointer (EPTP)
+ * @{
+ */
+/** Uncachable EPT paging structure memory type. */
+#define VMX_EPT_MEMTYPE_UC 0
+/** Write-back EPT paging structure memory type. */
+#define VMX_EPT_MEMTYPE_WB 6
+/** Shift value to get the EPT page walk length (bits 5-3) */
+#define VMX_EPT_PAGE_WALK_LENGTH_SHIFT 3
+/** Mask value to get the EPT page walk length (bits 5-3) */
+#define VMX_EPT_PAGE_WALK_LENGTH_MASK 7
+/** Default EPT page walk length */
+#define VMX_EPT_PAGE_WALK_LENGTH_DEFAULT 3
+/** @} */
+
+
+/** @name VMCS field encoding - 16 bits guest fields
+ * @{
+ */
+#define VMX_VMCS16_GUEST_FIELD_VPID 0x0
+#define VMX_VMCS16_GUEST_FIELD_ES 0x800
+#define VMX_VMCS16_GUEST_FIELD_CS 0x802
+#define VMX_VMCS16_GUEST_FIELD_SS 0x804
+#define VMX_VMCS16_GUEST_FIELD_DS 0x806
+#define VMX_VMCS16_GUEST_FIELD_FS 0x808
+#define VMX_VMCS16_GUEST_FIELD_GS 0x80A
+#define VMX_VMCS16_GUEST_FIELD_LDTR 0x80C
+#define VMX_VMCS16_GUEST_FIELD_TR 0x80E
+/** @} */
+
+/** @name VMCS field encoding - 16 bits host fields
+ * @{
+ */
+#define VMX_VMCS16_HOST_FIELD_ES 0xC00
+#define VMX_VMCS16_HOST_FIELD_CS 0xC02
+#define VMX_VMCS16_HOST_FIELD_SS 0xC04
+#define VMX_VMCS16_HOST_FIELD_DS 0xC06
+#define VMX_VMCS16_HOST_FIELD_FS 0xC08
+#define VMX_VMCS16_HOST_FIELD_GS 0xC0A
+#define VMX_VMCS16_HOST_FIELD_TR 0xC0C
+/** @} */
+
+/** @name VMCS field encoding - 64 bits host fields
+ * @{
+ */
+#define VMX_VMCS_HOST_FIELD_PAT_FULL 0x2C00
+#define VMX_VMCS_HOST_FIELD_PAT_HIGH 0x2C01
+#define VMX_VMCS_HOST_FIELD_EFER_FULL 0x2C02
+#define VMX_VMCS_HOST_FIELD_EFER_HIGH 0x2C03
+#define VMX_VMCS_HOST_PERF_GLOBAL_CTRL_FULL 0x2C04 /**< MSR IA32_PERF_GLOBAL_CTRL */
+#define VMX_VMCS_HOST_PERF_GLOBAL_CTRL_HIGH 0x2C05 /**< MSR IA32_PERF_GLOBAL_CTRL */
+/** @} */
+
+
+/** @name VMCS field encoding - 64 Bits control fields
+ * @{
+ */
+#define VMX_VMCS_CTRL_IO_BITMAP_A_FULL 0x2000
+#define VMX_VMCS_CTRL_IO_BITMAP_A_HIGH 0x2001
+#define VMX_VMCS_CTRL_IO_BITMAP_B_FULL 0x2002
+#define VMX_VMCS_CTRL_IO_BITMAP_B_HIGH 0x2003
+
+/* Optional */
+#define VMX_VMCS_CTRL_MSR_BITMAP_FULL 0x2004
+#define VMX_VMCS_CTRL_MSR_BITMAP_HIGH 0x2005
+
+#define VMX_VMCS_CTRL_VMEXIT_MSR_STORE_FULL 0x2006
+#define VMX_VMCS_CTRL_VMEXIT_MSR_STORE_HIGH 0x2007
+#define VMX_VMCS_CTRL_VMEXIT_MSR_LOAD_FULL 0x2008
+#define VMX_VMCS_CTRL_VMEXIT_MSR_LOAD_HIGH 0x2009
+
+#define VMX_VMCS_CTRL_VMENTRY_MSR_LOAD_FULL 0x200A
+#define VMX_VMCS_CTRL_VMENTRY_MSR_LOAD_HIGH 0x200B
+
+#define VMX_VMCS_CTRL_EXEC_VMCS_PTR_FULL 0x200C
+#define VMX_VMCS_CTRL_EXEC_VMCS_PTR_HIGH 0x200D
+
+#define VMX_VMCS_CTRL_TSC_OFFSET_FULL 0x2010
+#define VMX_VMCS_CTRL_TSC_OFFSET_HIGH 0x2011
+
+/** Optional (VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW) */
+#define VMX_VMCS_CTRL_VAPIC_PAGEADDR_FULL 0x2012
+#define VMX_VMCS_CTRL_VAPIC_PAGEADDR_HIGH 0x2013
+
+/** Optional (VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC) */
+#define VMX_VMCS_CTRL_APIC_ACCESSADDR_FULL 0x2014
+#define VMX_VMCS_CTRL_APIC_ACCESSADDR_HIGH 0x2015
+
+/** Extended page table pointer. */
+#define VMX_VMCS_CTRL_EPTP_FULL 0x201a
+#define VMX_VMCS_CTRL_EPTP_HIGH 0x201b
+
+/** VM-exit phyiscal address. */
+#define VMX_VMCS_EXIT_PHYS_ADDR_FULL 0x2400
+#define VMX_VMCS_EXIT_PHYS_ADDR_HIGH 0x2401
+/** @} */
+
+
+/** @name VMCS field encoding - 64 Bits guest fields
+ * @{
+ */
+#define VMX_VMCS_GUEST_LINK_PTR_FULL 0x2800
+#define VMX_VMCS_GUEST_LINK_PTR_HIGH 0x2801
+#define VMX_VMCS_GUEST_DEBUGCTL_FULL 0x2802 /**< MSR IA32_DEBUGCTL */
+#define VMX_VMCS_GUEST_DEBUGCTL_HIGH 0x2803 /**< MSR IA32_DEBUGCTL */
+#define VMX_VMCS_GUEST_PAT_FULL 0x2804
+#define VMX_VMCS_GUEST_PAT_HIGH 0x2805
+#define VMX_VMCS_GUEST_EFER_FULL 0x2806
+#define VMX_VMCS_GUEST_EFER_HIGH 0x2807
+#define VMX_VMCS_GUEST_PERF_GLOBAL_CTRL_FULL 0x2808 /**< MSR IA32_PERF_GLOBAL_CTRL */
+#define VMX_VMCS_GUEST_PERF_GLOBAL_CTRL_HIGH 0x2809 /**< MSR IA32_PERF_GLOBAL_CTRL */
+#define VMX_VMCS_GUEST_PDPTR0_FULL 0x280A
+#define VMX_VMCS_GUEST_PDPTR0_HIGH 0x280B
+#define VMX_VMCS_GUEST_PDPTR1_FULL 0x280C
+#define VMX_VMCS_GUEST_PDPTR1_HIGH 0x280D
+#define VMX_VMCS_GUEST_PDPTR2_FULL 0x280E
+#define VMX_VMCS_GUEST_PDPTR2_HIGH 0x280F
+#define VMX_VMCS_GUEST_PDPTR3_FULL 0x2810
+#define VMX_VMCS_GUEST_PDPTR3_HIGH 0x2811
+/** @} */
+
+
+/** @name VMCS field encoding - 32 Bits control fields
+ * @{
+ */
+#define VMX_VMCS_CTRL_PIN_EXEC_CONTROLS 0x4000
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS 0x4002
+#define VMX_VMCS_CTRL_EXCEPTION_BITMAP 0x4004
+#define VMX_VMCS_CTRL_PAGEFAULT_ERROR_MASK 0x4006
+#define VMX_VMCS_CTRL_PAGEFAULT_ERROR_MATCH 0x4008
+#define VMX_VMCS_CTRL_CR3_TARGET_COUNT 0x400A
+#define VMX_VMCS_CTRL_EXIT_CONTROLS 0x400C
+#define VMX_VMCS_CTRL_EXIT_MSR_STORE_COUNT 0x400E
+#define VMX_VMCS_CTRL_EXIT_MSR_LOAD_COUNT 0x4010
+#define VMX_VMCS_CTRL_ENTRY_CONTROLS 0x4012
+#define VMX_VMCS_CTRL_ENTRY_MSR_LOAD_COUNT 0x4014
+#define VMX_VMCS_CTRL_ENTRY_IRQ_INFO 0x4016
+#define VMX_VMCS_CTRL_ENTRY_EXCEPTION_ERRCODE 0x4018
+#define VMX_VMCS_CTRL_ENTRY_INSTR_LENGTH 0x401A
+/** This field exists only on processors that support the 1-setting of the “use TPR shadow” VM-execution control. */
+#define VMX_VMCS_CTRL_TPR_THRESHOLD 0x401C
+/** This field exists only on processors that support the 1-setting of the “activate secondary controls” VM-execution control. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS2 0x401E
+/** @} */
+
+
+/** @name VMX_VMCS_CTRL_PIN_EXEC_CONTROLS
+ * @{
+ */
+/** External interrupts cause VM exits if set; otherwise dispatched through the guest's IDT. */
+#define VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_EXT_INT_EXIT RT_BIT(0)
+/** Non-maskable interrupts cause VM exits if set; otherwise dispatched through the guest's IDT. */
+#define VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_NMI_EXIT RT_BIT(3)
+/** Virtual NMIs. */
+#define VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_VIRTUAL_NMI RT_BIT(5)
+/** Activate VMX preemption timer. */
+#define VMX_VMCS_CTRL_PIN_EXEC_CONTROLS_PREEMPT_TIMER RT_BIT(6)
+/* All other bits are reserved and must be set according to MSR IA32_VMX_PROCBASED_CTLS. */
+/** @} */
+
+/** @name VMX_VMCS_CTRL_PROC_EXEC_CONTROLS
+ * @{
+ */
+/** VM Exit as soon as RFLAGS.IF=1 and no blocking is active. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_IRQ_WINDOW_EXIT RT_BIT(2)
+/** Use timestamp counter offset. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_TSC_OFFSET RT_BIT(3)
+/** VM Exit when executing the HLT instruction. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_HLT_EXIT RT_BIT(7)
+/** VM Exit when executing the INVLPG instruction. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INVLPG_EXIT RT_BIT(9)
+/** VM Exit when executing the MWAIT instruction. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MWAIT_EXIT RT_BIT(10)
+/** VM Exit when executing the RDPMC instruction. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDPMC_EXIT RT_BIT(11)
+/** VM Exit when executing the RDTSC/RDTSCP instruction. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT RT_BIT(12)
+/** VM Exit when executing the MOV to CR3 instruction. (forced to 1 on the 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR3_LOAD_EXIT RT_BIT(15)
+/** VM Exit when executing the MOV from CR3 instruction. (forced to 1 on the 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR3_STORE_EXIT RT_BIT(16)
+/** VM Exit on CR8 loads. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_LOAD_EXIT RT_BIT(19)
+/** VM Exit on CR8 stores. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_CR8_STORE_EXIT RT_BIT(20)
+/** Use TPR shadow. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_TPR_SHADOW RT_BIT(21)
+/** VM Exit when virtual nmi blocking is disabled. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_NMI_WINDOW_EXIT RT_BIT(22)
+/** VM Exit when executing a MOV DRx instruction. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MOV_DR_EXIT RT_BIT(23)
+/** VM Exit when executing IO instructions. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_UNCOND_IO_EXIT RT_BIT(24)
+/** Use IO bitmaps. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_IO_BITMAPS RT_BIT(25)
+/** Monitor trap flag. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MONITOR_TRAP_FLAG RT_BIT(27)
+/** Use MSR bitmaps. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_USE_MSR_BITMAPS RT_BIT(28)
+/** VM Exit when executing the MONITOR instruction. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MONITOR_EXIT RT_BIT(29)
+/** VM Exit when executing the PAUSE instruction. */
+#define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_PAUSE_EXIT RT_BIT(30)
+/** Determines whether the secondary processor based VM-execution controls are used. */
+#define VMX_VMCS_CTRL_PROC_EXEC_USE_SECONDARY_EXEC_CTRL RT_BIT(31)
+/** @} */
+
+/** @name VMX_VMCS_CTRL_PROC_EXEC_CONTROLS2
+ * @{
+ */
+/** Virtualize APIC access. */
+#define VMX_VMCS_CTRL_PROC_EXEC2_VIRT_APIC RT_BIT(0)
+/** EPT supported/enabled. */
+#define VMX_VMCS_CTRL_PROC_EXEC2_EPT RT_BIT(1)
+/** Descriptor table instructions cause VM-exits. */
+#define VMX_VMCS_CTRL_PROC_EXEC2_DESCRIPTOR_INSTR_EXIT RT_BIT(2)
+/** RDTSCP supported/enabled. */
+#define VMX_VMCS_CTRL_PROC_EXEC2_RDTSCP RT_BIT(3)
+/** Virtualize x2APIC mode. */
+#define VMX_VMCS_CTRL_PROC_EXEC2_X2APIC RT_BIT(4)
+/** VPID supported/enabled. */
+#define VMX_VMCS_CTRL_PROC_EXEC2_VPID RT_BIT(5)
+/** VM Exit when executing the WBINVD instruction. */
+#define VMX_VMCS_CTRL_PROC_EXEC2_WBINVD_EXIT RT_BIT(6)
+/** Unrestricted guest execution. */
+#define VMX_VMCS_CTRL_PROC_EXEC2_REAL_MODE RT_BIT(7)
+/** A specified nr of pause loops cause a VM-exit. */
+#define VMX_VMCS_CTRL_PROC_EXEC2_PAUSE_LOOP_EXIT RT_BIT(10)
+/** @} */
+
+
+/** @name VMX_VMCS_CTRL_ENTRY_CONTROLS
+ * @{
+ */
+/** Load guest debug controls (dr7 & IA32_DEBUGCTL_MSR) (forced to 1 on the 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */
+#define VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_DEBUG RT_BIT(2)
+/** 64 bits guest mode. Must be 0 for CPUs that don't support AMD64. */
+#define VMX_VMCS_CTRL_ENTRY_CONTROLS_IA64_MODE RT_BIT(9)
+/** In SMM mode after VM-entry. */
+#define VMX_VMCS_CTRL_ENTRY_CONTROLS_ENTRY_SMM RT_BIT(10)
+/** Disable dual treatment of SMI and SMM; must be zero for VM-entry outside of SMM. */
+#define VMX_VMCS_CTRL_ENTRY_CONTROLS_DEACTIVATE_DUALMON RT_BIT(11)
+/** This control determines whether the guest IA32_PERF_GLOBAL_CTRL MSR is loaded on VM entry. */
+#define VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_PERF_MSR RT_BIT(13)
+/** This control determines whether the guest IA32_PAT MSR is loaded on VM entry. */
+#define VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_PAT_MSR RT_BIT(14)
+/** This control determines whether the guest IA32_EFER MSR is loaded on VM entry. */
+#define VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_GUEST_EFER_MSR RT_BIT(15)
+/** @} */
+
+
+/** @name VMX_VMCS_CTRL_EXIT_CONTROLS
+ * @{
+ */
+/** Save guest debug controls (dr7 & IA32_DEBUGCTL_MSR) (forced to 1 on the 'first' VT-x capable CPUs; this actually includes the newest Nehalem CPUs) */
+#define VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_DEBUG RT_BIT(2)
+/** Return to long mode after a VM-exit. */
+#define VMX_VMCS_CTRL_EXIT_CONTROLS_HOST_AMD64 RT_BIT(9)
+/** This control determines whether the IA32_PERF_GLOBAL_CTRL MSR is loaded on VM exit. */
+#define VMX_VMCS_CTRL_EXIT_CONTROLS_LOAD_PERF_MSR RT_BIT(12)
+/** Acknowledge external interrupts with the irq controller if one caused a VM-exit. */
+#define VMX_VMCS_CTRL_EXIT_CONTROLS_ACK_EXTERNAL_IRQ RT_BIT(15)
+/** This control determines whether the guest IA32_PAT MSR is saved on VM exit. */
+#define VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_GUEST_PAT_MSR RT_BIT(18)
+/** This control determines whether the host IA32_PAT MSR is loaded on VM exit. */
+#define VMX_VMCS_CTRL_EXIT_CONTROLS_LOAD_HOST_PAT_MSR RT_BIT(19)
+/** This control determines whether the guest IA32_EFER MSR is saved on VM exit. */
+#define VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_GUEST_EFER_MSR RT_BIT(20)
+/** This control determines whether the host IA32_EFER MSR is loaded on VM exit. */
+#define VMX_VMCS_CTRL_EXIT_CONTROLS_LOAD_HOST_EFER_MSR RT_BIT(21)
+/** This control determines whether the value of the VMX preemption timer is saved on VM exit. */
+#define VMX_VMCS_CTRL_EXIT_CONTROLS_SAVE_VMX_PREEMPT_TIMER RT_BIT(22)
+/** @} */
+
+/** @name VMCS field encoding - 32 Bits read-only fields
+ * @{
+ */
+#define VMX_VMCS32_RO_VM_INSTR_ERROR 0x4400
+#define VMX_VMCS32_RO_EXIT_REASON 0x4402
+#define VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO 0x4404
+#define VMX_VMCS32_RO_EXIT_INTERRUPTION_ERRCODE 0x4406
+#define VMX_VMCS32_RO_IDT_INFO 0x4408
+#define VMX_VMCS32_RO_IDT_ERRCODE 0x440A
+#define VMX_VMCS32_RO_EXIT_INSTR_LENGTH 0x440C
+#define VMX_VMCS32_RO_EXIT_INSTR_INFO 0x440E
+/** @} */
+
+/** @name VMX_VMCS_RO_EXIT_INTERRUPTION_INFO
+ * @{
+ */
+#define VMX_EXIT_INTERRUPTION_INFO_VECTOR(a) (a & 0xff)
+#define VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT 8
+#define VMX_EXIT_INTERRUPTION_INFO_TYPE(a) ((a >> VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT) & 7)
+#define VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID RT_BIT(11)
+#define VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_IS_VALID(a) (a & VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID)
+#define VMX_EXIT_INTERRUPTION_INFO_NMI_UNBLOCK(a) (a & RT_BIT(12))
+#define VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT 31
+#define VMX_EXIT_INTERRUPTION_INFO_VALID(a) (a & RT_BIT(31))
+/** Construct an irq event injection value from the exit interruption info value (same except that bit 12 is reserved). */
+#define VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(a) (a & ~RT_BIT(12))
+/** @} */
+
+/** @name VMX_VMCS_RO_EXIT_INTERRUPTION_INFO_TYPE
+ * @{
+ */
+#define VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT 0
+#define VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI 2
+#define VMX_EXIT_INTERRUPTION_INFO_TYPE_HWEXCPT 3
+#define VMX_EXIT_INTERRUPTION_INFO_TYPE_SW 4 /**< int xx */
+#define VMX_EXIT_INTERRUPTION_INFO_TYPE_DBEXCPT 5 /**< Why are we getting this one?? */
+#define VMX_EXIT_INTERRUPTION_INFO_TYPE_SWEXCPT 6
+/** @} */
+
+
+/** @name VMCS field encoding - 32 Bits guest state fields
+ * @{
+ */
+#define VMX_VMCS32_GUEST_ES_LIMIT 0x4800
+#define VMX_VMCS32_GUEST_CS_LIMIT 0x4802
+#define VMX_VMCS32_GUEST_SS_LIMIT 0x4804
+#define VMX_VMCS32_GUEST_DS_LIMIT 0x4806
+#define VMX_VMCS32_GUEST_FS_LIMIT 0x4808
+#define VMX_VMCS32_GUEST_GS_LIMIT 0x480A
+#define VMX_VMCS32_GUEST_LDTR_LIMIT 0x480C
+#define VMX_VMCS32_GUEST_TR_LIMIT 0x480E
+#define VMX_VMCS32_GUEST_GDTR_LIMIT 0x4810
+#define VMX_VMCS32_GUEST_IDTR_LIMIT 0x4812
+#define VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS 0x4814
+#define VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS 0x4816
+#define VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS 0x4818
+#define VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS 0x481A
+#define VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS 0x481C
+#define VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS 0x481E
+#define VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS 0x4820
+#define VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS 0x4822
+#define VMX_VMCS32_GUEST_INTERRUPTIBILITY_STATE 0x4824
+#define VMX_VMCS32_GUEST_ACTIVITY_STATE 0x4826
+#define VMX_VMCS32_GUEST_SYSENTER_CS 0x482A /**< MSR IA32_SYSENTER_CS */
+#define VMX_VMCS32_GUEST_PREEMPTION_TIMER_VALUE 0x482E
+/** @} */
+
+
+/** @name VMX_VMCS_GUEST_ACTIVITY_STATE
+ * @{
+ */
+/** The logical processor is active. */
+#define VMX_CMS_GUEST_ACTIVITY_ACTIVE 0x0
+/** The logical processor is inactive, because executed a HLT instruction. */
+#define VMX_CMS_GUEST_ACTIVITY_HLT 0x1
+/** The logical processor is inactive, because of a triple fault or other serious error. */
+#define VMX_CMS_GUEST_ACTIVITY_SHUTDOWN 0x2
+/** The logical processor is inactive, because it's waiting for a startup-IPI */
+#define VMX_CMS_GUEST_ACTIVITY_SIPI_WAIT 0x3
+/** @} */
+
+
+/** @name VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE
+ * @{
+ */
+#define VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_STI RT_BIT(0)
+#define VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_MOVSS RT_BIT(1)
+#define VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_SMI RT_BIT(2)
+#define VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_NMI RT_BIT(3)
+/** @} */
+
+
+/** @name VMCS field encoding - 32 Bits host state fields
+ * @{
+ */
+#define VMX_VMCS32_HOST_SYSENTER_CS 0x4C00
+/** @} */
+
+/** @name Natural width control fields
+ * @{
+ */
+#define VMX_VMCS_CTRL_CR0_MASK 0x6000
+#define VMX_VMCS_CTRL_CR4_MASK 0x6002
+#define VMX_VMCS_CTRL_CR0_READ_SHADOW 0x6004
+#define VMX_VMCS_CTRL_CR4_READ_SHADOW 0x6006
+#define VMX_VMCS_CTRL_CR3_TARGET_VAL0 0x6008
+#define VMX_VMCS_CTRL_CR3_TARGET_VAL1 0x600A
+#define VMX_VMCS_CTRL_CR3_TARGET_VAL2 0x600C
+#define VMX_VMCS_CTRL_CR3_TARGET_VAL31 0x600E
+/** @} */
+
+
+/** @name Natural width read-only data fields
+ * @{
+ */
+#define VMX_VMCS_RO_EXIT_QUALIFICATION 0x6400
+#define VMX_VMCS_RO_IO_RCX 0x6402
+#define VMX_VMCS_RO_IO_RSX 0x6404
+#define VMX_VMCS_RO_IO_RDI 0x6406
+#define VMX_VMCS_RO_IO_RIP 0x6408
+#define VMX_VMCS_EXIT_GUEST_LINEAR_ADDR 0x640A
+/** @} */
+
+
+/** @name VMX_VMCS_RO_EXIT_QUALIFICATION
+ * @{
+ */
+/** 0-2: Debug register number */
+#define VMX_EXIT_QUALIFICATION_DRX_REGISTER(a) (a & 7)
+/** 3: Reserved; cleared to 0. */
+#define VMX_EXIT_QUALIFICATION_DRX_RES1(a) ((a >> 3) & 1)
+/** 4: Direction of move (0 = write, 1 = read) */
+#define VMX_EXIT_QUALIFICATION_DRX_DIRECTION(a) ((a >> 4) & 1)
+/** 5-7: Reserved; cleared to 0. */
+#define VMX_EXIT_QUALIFICATION_DRX_RES2(a) ((a >> 5) & 7)
+/** 8-11: General purpose register number. */
+#define VMX_EXIT_QUALIFICATION_DRX_GENREG(a) ((a >> 8) & 0xF)
+/** Rest: reserved. */
+/** @} */
+
+/** @name VMX_EXIT_QUALIFICATION_DRX_DIRECTION values
+ * @{
+ */
+#define VMX_EXIT_QUALIFICATION_DRX_DIRECTION_WRITE 0
+#define VMX_EXIT_QUALIFICATION_DRX_DIRECTION_READ 1
+/** @} */
+
+
+
+/** @name CRx accesses
+ * @{
+ */
+/** 0-3: Control register number (0 for CLTS & LMSW) */
+#define VMX_EXIT_QUALIFICATION_CRX_REGISTER(a) (a & 0xF)
+/** 4-5: Access type. */
+#define VMX_EXIT_QUALIFICATION_CRX_ACCESS(a) ((a >> 4) & 3)
+/** 6: LMSW operand type */
+#define VMX_EXIT_QUALIFICATION_CRX_LMSW_OP(a) ((a >> 6) & 1)
+/** 7: Reserved; cleared to 0. */
+#define VMX_EXIT_QUALIFICATION_CRX_RES1(a) ((a >> 7) & 1)
+/** 8-11: General purpose register number (0 for CLTS & LMSW). */
+#define VMX_EXIT_QUALIFICATION_CRX_GENREG(a) ((a >> 8) & 0xF)
+/** 12-15: Reserved; cleared to 0. */
+#define VMX_EXIT_QUALIFICATION_CRX_RES2(a) ((a >> 12) & 0xF)
+/** 16-31: LMSW source data (else 0). */
+#define VMX_EXIT_QUALIFICATION_CRX_LMSW_DATA(a) ((a >> 16) & 0xFFFF)
+/** Rest: reserved. */
+/** @} */
+
+/** @name VMX_EXIT_QUALIFICATION_CRX_ACCESS
+ * @{
+ */
+#define VMX_EXIT_QUALIFICATION_CRX_ACCESS_WRITE 0
+#define VMX_EXIT_QUALIFICATION_CRX_ACCESS_READ 1
+#define VMX_EXIT_QUALIFICATION_CRX_ACCESS_CLTS 2
+#define VMX_EXIT_QUALIFICATION_CRX_ACCESS_LMSW 3
+/** @} */
+
+/** @name VMX_EXIT_QUALIFICATION_TASK_SWITCH
+ * @{
+ */
+#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SELECTOR(a) (a & 0xffff)
+#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE(a) ((a >> 30)& 0x3)
+/** Task switch caused by a call instruction. */
+#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE_CALL 0
+/** Task switch caused by an iret instruction. */
+#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE_IRET 1
+/** Task switch caused by a jmp instruction. */
+#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE_JMP 2
+/** Task switch caused by an interrupt gate. */
+#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_TYPE_IDT 3
+
+/** @} */
+
+
+/** @name VMX_EXIT_EPT_VIOLATION
+ * @{
+ */
+/** Set if the violation was caused by a data read. */
+#define VMX_EXIT_QUALIFICATION_EPT_DATA_READ RT_BIT(0)
+/** Set if the violation was caused by a data write. */
+#define VMX_EXIT_QUALIFICATION_EPT_DATA_WRITE RT_BIT(1)
+/** Set if the violation was caused by an insruction fetch. */
+#define VMX_EXIT_QUALIFICATION_EPT_INSTR_FETCH RT_BIT(2)
+/** AND of the present bit of all EPT structures. */
+#define VMX_EXIT_QUALIFICATION_EPT_ENTRY_PRESENT RT_BIT(3)
+/** AND of the write bit of all EPT structures. */
+#define VMX_EXIT_QUALIFICATION_EPT_ENTRY_WRITE RT_BIT(4)
+/** AND of the execute bit of all EPT structures. */
+#define VMX_EXIT_QUALIFICATION_EPT_ENTRY_EXECUTE RT_BIT(5)
+/** Set if the guest linear address field contains the faulting address. */
+#define VMX_EXIT_QUALIFICATION_EPT_GUEST_ADDR_VALID RT_BIT(7)
+/** If bit 7 is one: (reserved otherwise)
+ * 1 - violation due to physical address access.
+ * 0 - violation caused by page walk or access/dirty bit updates
+ */
+#define VMX_EXIT_QUALIFICATION_EPT_TRANSLATED_ACCESS RT_BIT(8)
+/** @} */
+
+
+/** @name VMX_EXIT_PORT_IO
+ * @{
+ */
+/** 0-2: IO operation width. */
+#define VMX_EXIT_QUALIFICATION_IO_WIDTH(a) (a & 7)
+/** 3: IO operation direction. */
+#define VMX_EXIT_QUALIFICATION_IO_DIRECTION(a) ((a >> 3) & 1)
+/** 4: String IO operation. */
+#define VMX_EXIT_QUALIFICATION_IO_STRING(a) ((a >> 4) & 1)
+/** 5: Repeated IO operation. */
+#define VMX_EXIT_QUALIFICATION_IO_REP(a) ((a >> 5) & 1)
+/** 6: Operand encoding. */
+#define VMX_EXIT_QUALIFICATION_IO_ENCODING(a) ((a >> 6) & 1)
+/** 16-31: IO Port (0-0xffff). */
+#define VMX_EXIT_QUALIFICATION_IO_PORT(a) ((a >> 16) & 0xffff)
+/* Rest reserved. */
+/** @} */
+
+/** @name VMX_EXIT_QUALIFICATION_IO_DIRECTION
+ * @{
+ */
+#define VMX_EXIT_QUALIFICATION_IO_DIRECTION_OUT 0
+#define VMX_EXIT_QUALIFICATION_IO_DIRECTION_IN 1
+/** @} */
+
+
+/** @name VMX_EXIT_QUALIFICATION_IO_ENCODING
+ * @{
+ */
+#define VMX_EXIT_QUALIFICATION_IO_ENCODING_DX 0
+#define VMX_EXIT_QUALIFICATION_IO_ENCODING_IMM 1
+/** @} */
+
+/** @name VMX_EXIT_APIC_ACCESS
+ * @{
+ */
+/** 0-11: If the APIC-access VM exit is due to a linear access, the offset of access within the APIC page. */
+#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_OFFSET(a) (a & 0xfff)
+/** 12-15: Access type. */
+#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_TYPE(a) ((a >> 12) & 0xf)
+/* Rest reserved. */
+/** @} */
+
+
+/** @name VMX_EXIT_QUALIFICATION_APIC_ACCESS_TYPE; access types
+ * @{
+ */
+/** Linear read access. */
+#define VMX_APIC_ACCESS_TYPE_LINEAR_READ 0
+/** Linear write access. */
+#define VMX_APIC_ACCESS_TYPE_LINEAR_WRITE 1
+/** Linear instruction fetch access. */
+#define VMX_APIC_ACCESS_TYPE_LINEAR_INSTR_FETCH 2
+/** Linear read/write access during event delivery. */
+#define VMX_APIC_ACCESS_TYPE_LINEAR_EVENT_DELIVERY 3
+/** Physical read/write access during event delivery. */
+#define VMX_APIC_ACCESS_TYPE_PHYSICAL_EVENT_DELIVERY 10
+/** Physical access for an instruction fetch or during instruction execution. */
+#define VMX_APIC_ACCESS_TYPE_PHYSICAL_INSTR 15
+/** @} */
+
+/** @} */
+
+/** @name VMCS field encoding - Natural width guest state fields
+ * @{
+ */
+#define VMX_VMCS64_GUEST_CR0 0x6800
+#define VMX_VMCS64_GUEST_CR3 0x6802
+#define VMX_VMCS64_GUEST_CR4 0x6804
+#define VMX_VMCS64_GUEST_ES_BASE 0x6806
+#define VMX_VMCS64_GUEST_CS_BASE 0x6808
+#define VMX_VMCS64_GUEST_SS_BASE 0x680A
+#define VMX_VMCS64_GUEST_DS_BASE 0x680C
+#define VMX_VMCS64_GUEST_FS_BASE 0x680E
+#define VMX_VMCS64_GUEST_GS_BASE 0x6810
+#define VMX_VMCS64_GUEST_LDTR_BASE 0x6812
+#define VMX_VMCS64_GUEST_TR_BASE 0x6814
+#define VMX_VMCS64_GUEST_GDTR_BASE 0x6816
+#define VMX_VMCS64_GUEST_IDTR_BASE 0x6818
+#define VMX_VMCS64_GUEST_DR7 0x681A
+#define VMX_VMCS64_GUEST_RSP 0x681C
+#define VMX_VMCS64_GUEST_RIP 0x681E
+#define VMX_VMCS_GUEST_RFLAGS 0x6820
+#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS 0x6822
+#define VMX_VMCS64_GUEST_SYSENTER_ESP 0x6824 /**< MSR IA32_SYSENTER_ESP */
+#define VMX_VMCS64_GUEST_SYSENTER_EIP 0x6826 /**< MSR IA32_SYSENTER_EIP */
+/** @} */
+
+
+/** @name VMX_VMCS_GUEST_DEBUG_EXCEPTIONS
+ * @{
+ */
+/** Hardware breakpoint 0 was met. */
+#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_B0 RT_BIT(0)
+/** Hardware breakpoint 1 was met. */
+#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_B1 RT_BIT(1)
+/** Hardware breakpoint 2 was met. */
+#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_B2 RT_BIT(2)
+/** Hardware breakpoint 3 was met. */
+#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_B3 RT_BIT(3)
+/** At least one data or IO breakpoint was hit. */
+#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_BREAKPOINT_ENABLED RT_BIT(12)
+/** A debug exception would have been triggered by single-step execution mode. */
+#define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS_BS RT_BIT(14)
+/** Bits 4-11, 13 and 15-63 are reserved. */
+
+/** @} */
+
+/** @name VMCS field encoding - Natural width host state fields
+ * @{
+ */
+#define VMX_VMCS_HOST_CR0 0x6C00
+#define VMX_VMCS_HOST_CR3 0x6C02
+#define VMX_VMCS_HOST_CR4 0x6C04
+#define VMX_VMCS_HOST_FS_BASE 0x6C06
+#define VMX_VMCS_HOST_GS_BASE 0x6C08
+#define VMX_VMCS_HOST_TR_BASE 0x6C0A
+#define VMX_VMCS_HOST_GDTR_BASE 0x6C0C
+#define VMX_VMCS_HOST_IDTR_BASE 0x6C0E
+#define VMX_VMCS_HOST_SYSENTER_ESP 0x6C10
+#define VMX_VMCS_HOST_SYSENTER_EIP 0x6C12
+#define VMX_VMCS_HOST_RSP 0x6C14
+#define VMX_VMCS_HOST_RIP 0x6C16
+/** @} */
+
+/** @} */
+
+
+#if RT_INLINE_ASM_GNU_STYLE
+# define __STR(x) #x
+# define STR(x) __STR(x)
+#endif
+
+
+/** @defgroup grp_vmx_asm vmx assembly helpers
+ * @ingroup grp_vmx
+ * @{
+ */
+
+/**
+ * Executes VMXON
+ *
+ * @returns VBox status code
+ * @param pVMXOn Physical address of VMXON structure
+ */
+#if RT_INLINE_ASM_EXTERNAL || HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
+DECLASM(int) VMXEnable(RTHCPHYS pVMXOn);
+#else
+DECLINLINE(int) VMXEnable(RTHCPHYS pVMXOn)
+{
+ int rc = VINF_SUCCESS;
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__ (
+ "push %3 \n\t"
+ "push %2 \n\t"
+ ".byte 0xF3, 0x0F, 0xC7, 0x34, 0x24 # VMXON [esp] \n\t"
+ "ja 2f \n\t"
+ "je 1f \n\t"
+ "movl $"STR(VERR_VMX_INVALID_VMXON_PTR)", %0 \n\t"
+ "jmp 2f \n\t"
+ "1: \n\t"
+ "movl $"STR(VERR_VMX_GENERIC)", %0 \n\t"
+ "2: \n\t"
+ "add $8, %%esp \n\t"
+ :"=rm"(rc)
+ :"0"(VINF_SUCCESS),
+ "ir"((uint32_t)pVMXOn), /* don't allow direct memory reference here, */
+ "ir"((uint32_t)(pVMXOn >> 32)) /* this would not work with -fomit-frame-pointer */
+ :"memory"
+ );
+# else
+ __asm
+ {
+ push dword ptr [pVMXOn+4]
+ push dword ptr [pVMXOn]
+ _emit 0xF3
+ _emit 0x0F
+ _emit 0xC7
+ _emit 0x34
+ _emit 0x24 /* VMXON [esp] */
+ jnc vmxon_good
+ mov dword ptr [rc], VERR_VMX_INVALID_VMXON_PTR
+ jmp the_end
+
+vmxon_good:
+ jnz the_end
+ mov dword ptr [rc], VERR_VMX_GENERIC
+the_end:
+ add esp, 8
+ }
+# endif
+ return rc;
+}
+#endif
+
+
+/**
+ * Executes VMXOFF
+ */
+#if RT_INLINE_ASM_EXTERNAL || HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
+DECLASM(void) VMXDisable(void);
+#else
+DECLINLINE(void) VMXDisable(void)
+{
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__ (
+ ".byte 0x0F, 0x01, 0xC4 # VMXOFF \n\t"
+ );
+# else
+ __asm
+ {
+ _emit 0x0F
+ _emit 0x01
+ _emit 0xC4 /* VMXOFF */
+ }
+# endif
+}
+#endif
+
+
+/**
+ * Executes VMCLEAR
+ *
+ * @returns VBox status code
+ * @param pVMCS Physical address of VM control structure
+ */
+#if RT_INLINE_ASM_EXTERNAL || HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
+DECLASM(int) VMXClearVMCS(RTHCPHYS pVMCS);
+#else
+DECLINLINE(int) VMXClearVMCS(RTHCPHYS pVMCS)
+{
+ int rc = VINF_SUCCESS;
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__ (
+ "push %3 \n\t"
+ "push %2 \n\t"
+ ".byte 0x66, 0x0F, 0xC7, 0x34, 0x24 # VMCLEAR [esp] \n\t"
+ "jnc 1f \n\t"
+ "movl $"STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "1: \n\t"
+ "add $8, %%esp \n\t"
+ :"=rm"(rc)
+ :"0"(VINF_SUCCESS),
+ "ir"((uint32_t)pVMCS), /* don't allow direct memory reference here, */
+ "ir"((uint32_t)(pVMCS >> 32)) /* this would not work with -fomit-frame-pointer */
+ :"memory"
+ );
+# else
+ __asm
+ {
+ push dword ptr [pVMCS+4]
+ push dword ptr [pVMCS]
+ _emit 0x66
+ _emit 0x0F
+ _emit 0xC7
+ _emit 0x34
+ _emit 0x24 /* VMCLEAR [esp] */
+ jnc success
+ mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
+success:
+ add esp, 8
+ }
+# endif
+ return rc;
+}
+#endif
+
+
+/**
+ * Executes VMPTRLD
+ *
+ * @returns VBox status code
+ * @param pVMCS Physical address of VMCS structure
+ */
+#if RT_INLINE_ASM_EXTERNAL || HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
+DECLASM(int) VMXActivateVMCS(RTHCPHYS pVMCS);
+#else
+DECLINLINE(int) VMXActivateVMCS(RTHCPHYS pVMCS)
+{
+ int rc = VINF_SUCCESS;
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__ (
+ "push %3 \n\t"
+ "push %2 \n\t"
+ ".byte 0x0F, 0xC7, 0x34, 0x24 # VMPTRLD [esp] \n\t"
+ "jnc 1f \n\t"
+ "movl $"STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "1: \n\t"
+ "add $8, %%esp \n\t"
+ :"=rm"(rc)
+ :"0"(VINF_SUCCESS),
+ "ir"((uint32_t)pVMCS), /* don't allow direct memory reference here, */
+ "ir"((uint32_t)(pVMCS >> 32)) /* this will not work with -fomit-frame-pointer */
+ );
+# else
+ __asm
+ {
+ push dword ptr [pVMCS+4]
+ push dword ptr [pVMCS]
+ _emit 0x0F
+ _emit 0xC7
+ _emit 0x34
+ _emit 0x24 /* VMPTRLD [esp] */
+ jnc success
+ mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
+
+success:
+ add esp, 8
+ }
+# endif
+ return rc;
+}
+#endif
+
+/**
+ * Executes VMPTRST
+ *
+ * @returns VBox status code
+ * @param pVMCS Address that will receive the current pointer
+ */
+DECLASM(int) VMXGetActivateVMCS(RTHCPHYS *pVMCS);
+
+/**
+ * Executes VMWRITE
+ *
+ * @returns VBox status code
+ * @param idxField VMCS index
+ * @param u32Val 32 bits value
+ */
+#if RT_INLINE_ASM_EXTERNAL || HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
+DECLASM(int) VMXWriteVMCS32(uint32_t idxField, uint32_t u32Val);
+#else
+DECLINLINE(int) VMXWriteVMCS32(uint32_t idxField, uint32_t u32Val)
+{
+ int rc = VINF_SUCCESS;
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__ (
+ ".byte 0x0F, 0x79, 0xC2 # VMWRITE eax, edx \n\t"
+ "ja 2f \n\t"
+ "je 1f \n\t"
+ "movl $"STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "jmp 2f \n\t"
+ "1: \n\t"
+ "movl $"STR(VERR_VMX_INVALID_VMCS_FIELD)", %0 \n\t"
+ "2: \n\t"
+ :"=rm"(rc)
+ :"0"(VINF_SUCCESS),
+ "a"(idxField),
+ "d"(u32Val)
+ );
+# else
+ __asm
+ {
+ push dword ptr [u32Val]
+ mov eax, [idxField]
+ _emit 0x0F
+ _emit 0x79
+ _emit 0x04
+ _emit 0x24 /* VMWRITE eax, [esp] */
+ jnc valid_vmcs
+ mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
+ jmp the_end
+
+valid_vmcs:
+ jnz the_end
+ mov dword ptr [rc], VERR_VMX_INVALID_VMCS_FIELD
+the_end:
+ add esp, 4
+ }
+# endif
+ return rc;
+}
+#endif
+
+/**
+ * Executes VMWRITE
+ *
+ * @returns VBox status code
+ * @param idxField VMCS index
+ * @param u64Val 16, 32 or 64 bits value
+ */
+#if HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
+DECLASM(int) VMXWriteVMCS64(uint32_t idxField, uint64_t u64Val);
+#else
+VMMR0DECL(int) VMXWriteVMCS64Ex(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val);
+
+#define VMXWriteVMCS64(idxField, u64Val) VMXWriteVMCS64Ex(pVCpu, idxField, u64Val)
+#endif
+
+#if HC_ARCH_BITS == 64
+#define VMXWriteVMCS VMXWriteVMCS64
+#else
+#define VMXWriteVMCS VMXWriteVMCS32
+#endif /* HC_ARCH_BITS == 64 */
+
+
+/**
+ * Invalidate a page using invept
+ * @returns VBox status code
+ * @param enmFlush Type of flush
+ * @param pDescriptor Descriptor
+ */
+DECLASM(int) VMXR0InvEPT(VMX_FLUSH_EPT enmFlush, uint64_t *pDescriptor);
+
+/**
+ * Invalidate a page using invvpid
+ * @returns VBox status code
+ * @param enmFlush Type of flush
+ * @param pDescriptor Descriptor
+ */
+DECLASM(int) VMXR0InvVPID(VMX_FLUSH_VPID enmFlush, uint64_t *pDescriptor);
+
+/**
+ * Executes VMREAD
+ *
+ * @returns VBox status code
+ * @param idxField VMCS index
+ * @param pData Ptr to store VM field value
+ */
+#if RT_INLINE_ASM_EXTERNAL || HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
+DECLASM(int) VMXReadVMCS32(uint32_t idxField, uint32_t *pData);
+#else
+DECLINLINE(int) VMXReadVMCS32(uint32_t idxField, uint32_t *pData)
+{
+ int rc = VINF_SUCCESS;
+# if RT_INLINE_ASM_GNU_STYLE
+ __asm__ __volatile__ (
+ "movl $"STR(VINF_SUCCESS)", %0 \n\t"
+ ".byte 0x0F, 0x78, 0xc2 # VMREAD eax, edx \n\t"
+ "ja 2f \n\t"
+ "je 1f \n\t"
+ "movl $"STR(VERR_VMX_INVALID_VMCS_PTR)", %0 \n\t"
+ "jmp 2f \n\t"
+ "1: \n\t"
+ "movl $"STR(VERR_VMX_INVALID_VMCS_FIELD)", %0 \n\t"
+ "2: \n\t"
+ :"=&r"(rc),
+ "=d"(*pData)
+ :"a"(idxField),
+ "d"(0)
+ );
+# else
+ __asm
+ {
+ sub esp, 4
+ mov dword ptr [esp], 0
+ mov eax, [idxField]
+ _emit 0x0F
+ _emit 0x78
+ _emit 0x04
+ _emit 0x24 /* VMREAD eax, [esp] */
+ mov edx, pData
+ pop dword ptr [edx]
+ jnc valid_vmcs
+ mov dword ptr [rc], VERR_VMX_INVALID_VMCS_PTR
+ jmp the_end
+
+valid_vmcs:
+ jnz the_end
+ mov dword ptr [rc], VERR_VMX_INVALID_VMCS_FIELD
+the_end:
+ }
+# endif
+ return rc;
+}
+#endif
+
+/**
+ * Executes VMREAD
+ *
+ * @returns VBox status code
+ * @param idxField VMCS index
+ * @param pData Ptr to store VM field value
+ */
+#if HC_ARCH_BITS == 64 || defined(VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0)
+DECLASM(int) VMXReadVMCS64(uint32_t idxField, uint64_t *pData);
+#else
+DECLINLINE(int) VMXReadVMCS64(uint32_t idxField, uint64_t *pData)
+{
+ int rc;
+
+ uint32_t val_hi, val;
+ rc = VMXReadVMCS32(idxField, &val);
+ rc |= VMXReadVMCS32(idxField + 1, &val_hi);
+ AssertRC(rc);
+ *pData = RT_MAKE_U64(val, val_hi);
+ return rc;
+}
+#endif
+
+#if HC_ARCH_BITS == 64
+# define VMXReadVMCS VMXReadVMCS64
+#else
+# define VMXReadVMCS VMXReadVMCS32
+#endif /* HC_ARCH_BITS == 64 */
+
+/**
+ * Gets the last instruction error value from the current VMCS
+ *
+ * @returns error value
+ */
+DECLINLINE(uint32_t) VMXGetLastError(void)
+{
+#if HC_ARCH_BITS == 64
+ uint64_t uLastError = 0;
+ int rc = VMXReadVMCS(VMX_VMCS32_RO_VM_INSTR_ERROR, &uLastError);
+ AssertRC(rc);
+ return (uint32_t)uLastError;
+
+#else /* 32-bit host: */
+ uint32_t uLastError = 0;
+ int rc = VMXReadVMCS32(VMX_VMCS32_RO_VM_INSTR_ERROR, &uLastError);
+ AssertRC(rc);
+ return uLastError;
+#endif
+}
+
+#ifdef IN_RING0
+VMMR0DECL(int) VMXR0InvalidatePage(PVM pVM, PVMCPU pVCpu, RTGCPTR GCVirt);
+VMMR0DECL(int) VMXR0InvalidatePhysPage(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys);
+#endif /* IN_RING0 */
+
+/** @} */
+
+#endif
+
diff --git a/include/VBox/vmm/hwacc_vmx.mac b/include/VBox/vmm/hwacc_vmx.mac
new file mode 100644
index 00000000..3fc11b43
--- /dev/null
+++ b/include/VBox/vmm/hwacc_vmx.mac
@@ -0,0 +1,154 @@
+;; @file
+; HWACCM - VMX Structures and Definitions.
+;
+
+;
+; Copyright (C) 2006-2010 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; 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.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+; VirtualBox OSE distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+
+%define VMX_VMCS_GUEST_FIELD_ES 0800h
+%define VMX_VMCS_GUEST_FIELD_CS 0802h
+%define VMX_VMCS_GUEST_FIELD_SS 0804h
+%define VMX_VMCS_GUEST_FIELD_DS 0806h
+%define VMX_VMCS_GUEST_FIELD_FS 0808h
+%define VMX_VMCS_GUEST_FIELD_GS 080Ah
+%define VMX_VMCS_GUEST_FIELD_LDTR 080Ch
+%define VMX_VMCS_GUEST_FIELD_TR 080Eh
+%define VMX_VMCS_HOST_FIELD_ES 0C00h
+%define VMX_VMCS_HOST_FIELD_CS 0C02h
+%define VMX_VMCS_HOST_FIELD_SS 0C04h
+%define VMX_VMCS_HOST_FIELD_DS 0C06h
+%define VMX_VMCS_HOST_FIELD_FS 0C08h
+%define VMX_VMCS_HOST_FIELD_GS 0C0Ah
+%define VMX_VMCS_HOST_FIELD_TR 0C0Ch
+%define VMX_VMCS_CTRL_IO_BITMAP_A_FULL 02000h
+%define VMX_VMCS_CTRL_IO_BITMAP_A_HIGH 02001h
+%define VMX_VMCS_CTRL_IO_BITMAP_B_FULL 02002h
+%define VMX_VMCS_CTRL_IO_BITMAP_B_HIGH 02003h
+%define VMX_VMCS_CTRL_MSR_BITMAP_FULL 02004h
+%define VMX_VMCS_CTRL_MSR_BITMAP_HIGH 02005h
+%define VMX_VMCS_CTRL_VMEXIT_MSR_STORE_FULL 02006h
+%define VMX_VMCS_CTRL_VMEXIT_MSR_STORE_HIGH 02007h
+%define VMX_VMCS_CTRL_VMEXIT_MSR_LOAD_FULL 02008h
+%define VMX_VMCS_CTRL_VMEXIT_MSR_LOAD_HIGH 02009h
+%define VMX_VMCS_CTRL_VMENTRY_MSR_LOAD_FULL 0200Ah
+%define VMX_VMCS_CTRL_VMENTRY_MSR_LOAD_HIGH 0200Bh
+%define VMX_VMCS_CTRL_EXEC_VMCS_PTR_FULL 0200Ch
+%define VMX_VMCS_CTRL_EXEC_VMCS_PTR_HIGH 0200Dh
+%define VMX_VMCS_CTRL_TSC_OFFSET_FULL 02010h
+%define VMX_VMCS_CTRL_TSC_OFFSET_HIGH 02011h
+%define VMX_VMCS_CTRL_VAPIC_PAGEADDR_FULL 02012h
+%define VMX_VMCS_CTRL_VAPIC_PAGEADDR_HIGH 02013h
+%define VMX_VMCS_GUEST_LINK_PTR_FULL 02800h
+%define VMX_VMCS_GUEST_LINK_PTR_HIGH 02801h
+%define VMX_VMCS_GUEST_DEBUGCTL_FULL 02802h
+%define VMX_VMCS_GUEST_DEBUGCTL_HIGH 02803h
+%define VMX_VMCS_CTRL_PIN_EXEC_CONTROLS 04000h
+%define VMX_VMCS_CTRL_PROC_EXEC_CONTROLS 04002h
+%define VMX_VMCS_CTRL_EXCEPTION_BITMAP 04004h
+%define VMX_VMCS_CTRL_PAGEFAULT_ERROR_MASK 04006h
+%define VMX_VMCS_CTRL_PAGEFAULT_ERROR_MATCH 04008h
+%define VMX_VMCS_CTRL_CR3_TARGET_COUNT 0400Ah
+%define VMX_VMCS_CTRL_EXIT_CONTROLS 0400Ch
+%define VMX_VMCS_CTRL_EXIT_MSR_STORE_COUNT 0400Eh
+%define VMX_VMCS_CTRL_EXIT_MSR_LOAD_COUNT 04010h
+%define VMX_VMCS_CTRL_ENTRY_CONTROLS 04012h
+%define VMX_VMCS_CTRL_ENTRY_MSR_LOAD_COUNT 04014h
+%define VMX_VMCS_CTRL_ENTRY_IRQ_INFO 04016h
+%define VMX_VMCS_CTRL_ENTRY_EXCEPTION_ERRCODE 04018h
+%define VMX_VMCS_CTRL_ENTRY_INSTR_LENGTH 0401Ah
+%define VMX_VMCS_CTRL_TRP_TRESHOLD 0401Ch
+%define VMX_VMCS_RO_VM_INSTR_ERROR 04400h
+%define VMX_VMCS_RO_EXIT_REASON 04402h
+%define VMX_VMCS_RO_EXIT_INTERRUPTION_INFO 04404h
+%define VMX_VMCS_RO_EXIT_INTERRUPTION_ERRCODE 04406h
+%define VMX_VMCS_RO_IDT_INFO 04408h
+%define VMX_VMCS_RO_IDT_ERRCODE 0440Ah
+%define VMX_VMCS_RO_EXIT_INSTR_LENGTH 0440Ch
+%define VMX_VMCS_RO_EXIT_INSTR_INFO 0440Eh
+%define VMX_VMCS_GUEST_ES_LIMIT 04800h
+%define VMX_VMCS_GUEST_CS_LIMIT 04802h
+%define VMX_VMCS_GUEST_SS_LIMIT 04804h
+%define VMX_VMCS_GUEST_DS_LIMIT 04806h
+%define VMX_VMCS_GUEST_FS_LIMIT 04808h
+%define VMX_VMCS_GUEST_GS_LIMIT 0480Ah
+%define VMX_VMCS_GUEST_LDTR_LIMIT 0480Ch
+%define VMX_VMCS_GUEST_TR_LIMIT 0480Eh
+%define VMX_VMCS_GUEST_GDTR_LIMIT 04810h
+%define VMX_VMCS_GUEST_IDTR_LIMIT 04812h
+%define VMX_VMCS_GUEST_ES_ACCESS_RIGHTS 04814h
+%define VMX_VMCS_GUEST_CS_ACCESS_RIGHTS 04816h
+%define VMX_VMCS_GUEST_SS_ACCESS_RIGHTS 04818h
+%define VMX_VMCS_GUEST_DS_ACCESS_RIGHTS 0481Ah
+%define VMX_VMCS_GUEST_FS_ACCESS_RIGHTS 0481Ch
+%define VMX_VMCS_GUEST_GS_ACCESS_RIGHTS 0481Eh
+%define VMX_VMCS_GUEST_LDTR_ACCESS_RIGHTS 04820h
+%define VMX_VMCS_GUEST_TR_ACCESS_RIGHTS 04822h
+%define VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE 04824h
+%define VMX_VMCS_GUEST_ACTIVITY_STATE 04826h
+%define VMX_VMCS_GUEST_SYSENTER_CS 0482Ah
+%define VMX_VMCS_CTRL_CR0_MASK 06000h
+%define VMX_VMCS_CTRL_CR4_MASK 06002h
+%define VMX_VMCS_CTRL_CR0_READ_SHADOW 06004h
+%define VMX_VMCS_CTRL_CR4_READ_SHADOW 06006h
+%define VMX_VMCS_CTRL_CR3_TARGET_VAL0 06008h
+%define VMX_VMCS_CTRL_CR3_TARGET_VAL1 0600Ah
+%define VMX_VMCS_CTRL_CR3_TARGET_VAL2 0600Ch
+%define VMX_VMCS_CTRL_CR3_TARGET_VAL31 0600Eh
+%define VMX_VMCS_RO_EXIT_QUALIFICATION 06400h
+%define VMX_VMCS_RO_IO_RCX 06402h
+%define VMX_VMCS_RO_IO_RSX 06404h
+%define VMX_VMCS_RO_IO_RDI 06406h
+%define VMX_VMCS_RO_IO_RIP 06408h
+%define VMX_VMCS_GUEST_LINEAR_ADDR 0640Ah
+%define VMX_VMCS64_GUEST_CR0 06800h
+%define VMX_VMCS64_GUEST_CR3 06802h
+%define VMX_VMCS64_GUEST_CR4 06804h
+%define VMX_VMCS64_GUEST_ES_BASE 06806h
+%define VMX_VMCS64_GUEST_CS_BASE 06808h
+%define VMX_VMCS64_GUEST_SS_BASE 0680Ah
+%define VMX_VMCS64_GUEST_DS_BASE 0680Ch
+%define VMX_VMCS64_GUEST_FS_BASE 0680Eh
+%define VMX_VMCS64_GUEST_GS_BASE 06810h
+%define VMX_VMCS64_GUEST_LDTR_BASE 06812h
+%define VMX_VMCS64_GUEST_TR_BASE 06814h
+%define VMX_VMCS64_GUEST_GDTR_BASE 06816h
+%define VMX_VMCS64_GUEST_IDTR_BASE 06818h
+%define VMX_VMCS64_GUEST_DR7 0681Ah
+%define VMX_VMCS64_GUEST_RSP 0681Ch
+%define VMX_VMCS64_GUEST_RIP 0681Eh
+%define VMX_VMCS64_GUEST_RFLAGS 06820h
+%define VMX_VMCS_GUEST_DEBUG_EXCEPTIONS 06822h
+%define VMX_VMCS64_GUEST_SYSENTER_ESP 06824h
+%define VMX_VMCS64_GUEST_SYSENTER_EIP 06826h
+%define VMX_VMCS_HOST_CR0 06C00h
+%define VMX_VMCS_HOST_CR3 06C02h
+%define VMX_VMCS_HOST_CR4 06C04h
+%define VMX_VMCS_HOST_FS_BASE 06C06h
+%define VMX_VMCS_HOST_GS_BASE 06C08h
+%define VMX_VMCS_HOST_TR_BASE 06C0Ah
+%define VMX_VMCS_HOST_GDTR_BASE 06C0Ch
+%define VMX_VMCS_HOST_IDTR_BASE 06C0Eh
+%define VMX_VMCS_HOST_SYSENTER_ESP 06C10h
+%define VMX_VMCS_HOST_SYSENTER_EIP 06C12h
+%define VMX_VMCS_HOST_RSP 06C14h
+%define VMX_VMCS_HOST_RIP 06C16h
+
+%define VMX_VMCS_CTRL_EXIT_CONTROLS_HOST_AMD64 RT_BIT(9)
diff --git a/include/VBox/vmm/hwaccm.h b/include/VBox/vmm/hwaccm.h
new file mode 100644
index 00000000..98a7d02e
--- /dev/null
+++ b/include/VBox/vmm/hwaccm.h
@@ -0,0 +1,154 @@
+/** @file
+ * HWACCM - Intel/AMD VM Hardware Support Manager (VMM)
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_hwaccm_h
+#define ___VBox_vmm_hwaccm_h
+
+#include <VBox/vmm/pgm.h>
+#include <VBox/vmm/cpum.h>
+#include <iprt/mp.h>
+
+
+/** @defgroup grp_hwaccm The VM Hardware Manager API
+ * @{
+ */
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Query HWACCM state (enabled/disabled)
+ *
+ * @returns 0 - disabled, 1 - enabled
+ * @param pVM The VM to operate on.
+ */
+#define HWACCMIsEnabled(pVM) ((pVM)->fHWACCMEnabled)
+
+ /**
+ * Check if the current CPU state is valid for emulating IO blocks in the recompiler
+ *
+ * @returns boolean
+ * @param pCtx CPU context
+ */
+#define HWACCMCanEmulateIoBlock(pVCpu) (!CPUMIsGuestInPagedProtectedMode(pVCpu))
+#define HWACCMCanEmulateIoBlockEx(pCtx) (!CPUMIsGuestInPagedProtectedModeEx(pCtx))
+
+VMMDECL(int) HWACCMInvalidatePage(PVMCPU pVCpu, RTGCPTR GCVirt);
+VMMDECL(bool) HWACCMHasPendingIrq(PVM pVM);
+
+#ifndef IN_RC
+VMMDECL(int) HWACCMFlushTLB(PVMCPU pVCpu);
+VMMDECL(int) HWACCMFlushTLBOnAllVCpus(PVM pVM);
+VMMDECL(int) HWACCMInvalidatePageOnAllVCpus(PVM pVM, RTGCPTR GCVirt);
+VMMDECL(int) HWACCMInvalidatePhysPage(PVM pVM, RTGCPHYS GCPhys);
+VMMDECL(bool) HWACCMIsNestedPagingActive(PVM pVM);
+VMMDECL(PGMMODE) HWACCMGetShwPagingMode(PVM pVM);
+#else
+/* Nop in GC */
+# define HWACCMFlushTLB(pVCpu) do { } while (0)
+# define HWACCMIsNestedPagingActive(pVM) false
+# define HWACCMFlushTLBOnAllVCpus(pVM) do { } while (0)
+#endif
+
+#ifdef IN_RING0
+/** @defgroup grp_hwaccm_r0 The VM Hardware Manager API
+ * @ingroup grp_hwaccm
+ * @{
+ */
+VMMR0DECL(int) HWACCMR0Init(void);
+VMMR0DECL(int) HWACCMR0Term(void);
+VMMR0DECL(int) HWACCMR0InitVM(PVM pVM);
+VMMR0DECL(int) HWACCMR0TermVM(PVM pVM);
+VMMR0DECL(int) HWACCMR0EnableAllCpus(PVM pVM);
+VMMR0DECL(int) HWACCMR0EnterSwitcher(PVM pVM, bool *pfVTxDisabled);
+VMMR0DECL(int) HWACCMR0LeaveSwitcher(PVM pVM, bool fVTxDisabled);
+
+VMMR0DECL(void) HWACCMR0SavePendingIOPortWrite(PVMCPU pVCpu, RTGCPTR GCPtrRip, RTGCPTR GCPtrRipNext, unsigned uPort, unsigned uAndVal, unsigned cbSize);
+VMMR0DECL(void) HWACCMR0SavePendingIOPortRead(PVMCPU pVCpu, RTGCPTR GCPtrRip, RTGCPTR GCPtrRipNext, unsigned uPort, unsigned uAndVal, unsigned cbSize);
+
+/** @} */
+#endif /* IN_RING0 */
+
+
+#ifdef IN_RING3
+/** @defgroup grp_hwaccm_r3 The VM Hardware Manager API
+ * @ingroup grp_hwaccm
+ * @{
+ */
+VMMR3DECL(bool) HWACCMR3IsEventPending(PVMCPU pVCpu);
+VMMR3DECL(int) HWACCMR3Init(PVM pVM);
+VMMR3_INT_DECL(int) HWACCMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
+VMMR3DECL(void) HWACCMR3Relocate(PVM pVM);
+VMMR3DECL(int) HWACCMR3Term(PVM pVM);
+VMMR3DECL(void) HWACCMR3Reset(PVM pVM);
+VMMR3DECL(void) HWACCMR3ResetCpu(PVMCPU pVCpu);
+VMMR3DECL(void) HWACCMR3CheckError(PVM pVM, int iStatusCode);
+VMMR3DECL(bool) HWACCMR3CanExecuteGuest(PVM pVM, PCPUMCTX pCtx);
+VMMR3DECL(void) HWACCMR3NotifyScheduled(PVMCPU pVCpu);
+VMMR3DECL(void) HWACCMR3NotifyEmulated(PVMCPU pVCpu);
+VMMR3DECL(bool) HWACCMR3IsActive(PVMCPU pVCpu);
+VMMR3DECL(bool) HWACCMR3IsNestedPagingActive(PVM pVM);
+VMMR3DECL(bool) HWACCMR3IsAllowed(PVM pVM);
+VMMR3DECL(void) HWACCMR3PagingModeChanged(PVM pVM, PVMCPU pVCpu, PGMMODE enmShadowMode, PGMMODE enmGuestMode);
+VMMR3DECL(bool) HWACCMR3IsVPIDActive(PVM pVM);
+VMMR3DECL(int) HWACCMR3InjectNMI(PVM pVM);
+VMMR3DECL(int) HWACCMR3EmulateIoBlock(PVM pVM, PCPUMCTX pCtx);
+VMMR3DECL(VBOXSTRICTRC) HWACCMR3RestartPendingIOInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
+VMMR3DECL(int) HWACMMR3EnablePatching(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem);
+VMMR3DECL(int) HWACMMR3DisablePatching(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem);
+VMMR3DECL(int) HWACCMR3PatchTprInstr(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
+VMMR3DECL(bool) HWACCMR3IsRescheduleRequired(PVM pVM, PCPUMCTX pCtx);
+VMMR3DECL(bool) HWACCMR3IsVmxPreemptionTimerUsed(PVM pVM);
+
+/** @} */
+#endif /* IN_RING3 */
+
+#ifdef IN_RING0
+/** @addtogroup grp_hwaccm_r0
+ * @{
+ */
+VMMR0DECL(int) HWACCMR0SetupVM(PVM pVM);
+VMMR0DECL(int) HWACCMR0RunGuestCode(PVM pVM, PVMCPU pVCpu);
+VMMR0DECL(int) HWACCMR0Enter(PVM pVM, PVMCPU pVCpu);
+VMMR0DECL(int) HWACCMR0Leave(PVM pVM, PVMCPU pVCpu);
+VMMR0DECL(int) HWACCMR0InvalidatePage(PVM pVM, PVMCPU pVCpu);
+VMMR0DECL(int) HWACCMR0FlushTLB(PVM pVM);
+VMMR0DECL(bool) HWACCMR0SuspendPending(void);
+
+# if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
+VMMR0DECL(int) HWACCMR0SaveFPUState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
+VMMR0DECL(int) HWACCMR0SaveDebugState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx);
+VMMR0DECL(int) HWACCMR0TestSwitcher3264(PVM pVM);
+# endif
+
+/** @} */
+#endif /* IN_RING0 */
+
+
+/** @} */
+RT_C_DECLS_END
+
+
+#endif
+
diff --git a/include/VBox/vmm/iem.h b/include/VBox/vmm/iem.h
new file mode 100644
index 00000000..617a05a6
--- /dev/null
+++ b/include/VBox/vmm/iem.h
@@ -0,0 +1,83 @@
+/** @file
+ * IEM - Interpreted Execution Manager.
+ */
+
+/*
+ * Copyright (C) 2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_iem_h
+#define ___VBox_vmm_iem_h
+
+#include <VBox/types.h>
+#include <VBox/vmm/trpm.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_iem The Interpreted Execution Manager API.
+ * @{
+ */
+
+
+
+VMMDECL(VBOXSTRICTRC) IEMExecOne(PVMCPU pVCpu);
+VMMDECL(VBOXSTRICTRC) IEMExecOneEx(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, uint32_t *pcbWritten);
+VMMDECL(VBOXSTRICTRC) IEMExecOneWithPrefetchedByPC(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, uint64_t OpcodeBytesPC,
+ const void *pvOpcodeBytes, size_t cbOpcodeBytes);
+VMMDECL(VBOXSTRICTRC) IEMExecOneBypassEx(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, uint32_t *pcbWritten);
+VMMDECL(VBOXSTRICTRC) IEMExecOneBypassWithPrefetchedByPC(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, uint64_t OpcodeBytesPC,
+ const void *pvOpcodeBytes, size_t cbOpcodeBytes);
+VMMDECL(VBOXSTRICTRC) IEMExecLots(PVMCPU pVCpu);
+VMM_INT_DECL(VBOXSTRICTRC) IEMInjectTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType, uint16_t uErrCode, RTGCPTR uCr2);
+
+VMM_INT_DECL(int) IEMBreakpointSet(PVM pVM, RTGCPTR GCPtrBp);
+VMM_INT_DECL(int) IEMBreakpointClear(PVM pVM, RTGCPTR GCPtrBp);
+
+/** @name Given Instruction Interpreters
+ * @{ */
+
+/** @} */
+
+#if defined(IEM_VERIFICATION_MODE) && defined(IN_RING3)
+VMM_INT_DECL(void) IEMNotifyMMIORead(PVM pVM, RTGCPHYS GCPhys, size_t cbValue);
+VMM_INT_DECL(void) IEMNotifyMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue);
+VMM_INT_DECL(void) IEMNotifyIOPortRead(PVM pVM, RTIOPORT Port, size_t cbValue);
+VMM_INT_DECL(void) IEMNotifyIOPortWrite(PVM pVM, RTIOPORT Port, uint32_t u32Value, size_t cbValue);
+VMM_INT_DECL(void) IEMNotifyIOPortReadString(PVM pVM, RTIOPORT Port, RTGCPTR GCPtrDst, RTGCUINTREG cTransfers, size_t cbValue);
+VMM_INT_DECL(void) IEMNotifyIOPortWriteString(PVM pVM, RTIOPORT Port, RTGCPTR GCPtrSrc, RTGCUINTREG cTransfers, size_t cbValue);
+#endif
+
+
+/** @defgroup grp_em_r3 The IEM Host Context Ring-3 API.
+ * @ingroup grp_em
+ * @{
+ */
+VMMR3DECL(int) IEMR3Init(PVM pVM);
+VMMR3DECL(int) IEMR3Term(PVM pVM);
+VMMR3DECL(void) IEMR3Relocate(PVM pVM);
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/iom.h b/include/VBox/vmm/iom.h
new file mode 100644
index 00000000..a7e552c9
--- /dev/null
+++ b/include/VBox/vmm/iom.h
@@ -0,0 +1,325 @@
+/** @file
+ * IOM - Input / Output Monitor.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_iom_h
+#define ___VBox_vmm_iom_h
+
+#include <VBox/types.h>
+#include <VBox/dis.h>
+
+RT_C_DECLS_BEGIN
+
+
+/** @defgroup grp_iom The Input / Ouput Monitor API
+ * @{
+ */
+
+/** @def IOM_NO_PDMINS_CHECKS
+ * Until all devices have been fully adjusted to PDM style, the pPdmIns
+ * parameter is not checked by IOM.
+ * @todo Check this again, now.
+ */
+#define IOM_NO_PDMINS_CHECKS
+
+/**
+ * Macro for checking if an I/O or MMIO emulation call succeeded.
+ *
+ * This macro shall only be used with the IOM APIs where it's mentioned
+ * in the return value description. And there it must be used to correctly
+ * determine if the call succeeded and things like the RIP needs updating.
+ *
+ *
+ * @returns Success indicator (true/false).
+ *
+ * @param rc The status code. This may be evaluated
+ * more than once!
+ *
+ * @remark To avoid making assumptions about the layout of the
+ * VINF_EM_FIRST...VINF_EM_LAST range we're checking
+ * explicitly for each for exach the exceptions.
+ * However, for efficieny we ASSUME that the
+ * VINF_EM_LAST is smaller than most of the relevant
+ * status codes. We also ASSUME that the
+ * VINF_EM_RESCHEDULE_REM status code is the most
+ * frequent status code we'll enounter in this range.
+ *
+ * @todo Will have to add VINF_EM_DBG_HYPER_BREAKPOINT if the
+ * I/O port and MMIO breakpoints should trigger before
+ * the I/O is done. Currently, we don't implement these
+ * kind of breakpoints.
+ */
+#define IOM_SUCCESS(rc) ( (rc) == VINF_SUCCESS \
+ || ( (rc) <= VINF_EM_LAST \
+ && (rc) != VINF_EM_RESCHEDULE_REM \
+ && (rc) >= VINF_EM_FIRST \
+ && (rc) != VINF_EM_RESCHEDULE_RAW \
+ && (rc) != VINF_EM_RESCHEDULE_HWACC \
+ ) \
+ )
+
+/** @name IOMMMIO_FLAGS_XXX
+ * @{ */
+/** Pass all reads thru unmodified. */
+#define IOMMMIO_FLAGS_READ_PASSTHRU UINT32_C(0x00000000)
+/** All read accesses are DWORD sized (32-bit). */
+#define IOMMMIO_FLAGS_READ_DWORD UINT32_C(0x00000001)
+/** All read accesses are DWORD (32-bit) or QWORD (64-bit) sized.
+ * Only accesses that are both QWORD sized and aligned are performed as QWORD.
+ * All other access will be done DWORD fashion (because it is way simpler). */
+#define IOMMMIO_FLAGS_READ_DWORD_QWORD UINT32_C(0x00000002)
+/** The read access mode mask. */
+#define IOMMMIO_FLAGS_READ_MODE UINT32_C(0x00000003)
+
+/** Pass all writes thru unmodified. */
+#define IOMMMIO_FLAGS_WRITE_PASSTHRU UINT32_C(0x00000000)
+/** All write accesses are DWORD (32-bit) sized and unspecified bytes are
+ * written as zero. */
+#define IOMMMIO_FLAGS_WRITE_DWORD_ZEROED UINT32_C(0x00000010)
+/** All write accesses are either DWORD (32-bit) or QWORD (64-bit) sized,
+ * missing bytes will be written as zero. Only accesses that are both QWORD
+ * sized and aligned are performed as QWORD, all other accesses will be done
+ * DWORD fashion (because it's way simpler). */
+#define IOMMMIO_FLAGS_WRITE_DWORD_QWORD_ZEROED UINT32_C(0x00000020)
+/** All write accesses are DWORD (32-bit) sized and unspecified bytes are
+ * read from the device first as DWORDs.
+ * @remarks This isn't how it happens on real hardware, but it allows
+ * simplifications of devices where reads doesn't change the device
+ * state in any way. */
+#define IOMMMIO_FLAGS_WRITE_DWORD_READ_MISSING UINT32_C(0x00000030)
+/** All write accesses are DWORD (32-bit) or QWORD (64-bit) sized and
+ * unspecified bytes are read from the device first as DWORDs. Only accesses
+ * that are both QWORD sized and aligned are performed as QWORD, all other
+ * accesses will be done DWORD fashion (because it's way simpler).
+ * @remarks This isn't how it happens on real hardware, but it allows
+ * simplifications of devices where reads doesn't change the device
+ * state in any way. */
+#define IOMMMIO_FLAGS_WRITE_DWORD_QWORD_READ_MISSING UINT32_C(0x00000040)
+/** The read access mode mask. */
+#define IOMMMIO_FLAGS_WRITE_MODE UINT32_C(0x00000070)
+
+/** Whether to do a DBGSTOP on complicated reads.
+ * What this includes depends on the read mode, but generally all misaligned
+ * reads as well as word and byte reads and maybe qword reads. */
+#define IOMMMIO_FLAGS_DBGSTOP_ON_COMPLICATED_READ UINT32_C(0x00000100)
+/** Whether to do a DBGSTOP on complicated writes.
+ * This depends on the write mode, but generally all writes where we have to
+ * supply bytes (zero them or read them). */
+#define IOMMMIO_FLAGS_DBGSTOP_ON_COMPLICATED_WRITE UINT32_C(0x00000200)
+
+/** Mask of valid flags. */
+#define IOMMMIO_FLAGS_VALID_MASK UINT32_C(0x00000373)
+/** @} */
+
+
+/**
+ * Port I/O Handler for IN operations.
+ *
+ * @returns VINF_SUCCESS or VINF_EM_*.
+ * @returns VERR_IOM_IOPORT_UNUSED if the port is really unused and a ~0 value should be returned.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param uPort Port number used for the IN operation.
+ * @param pu32 Where to store the result. This is always a 32-bit
+ * variable regardless of what @a cb might say.
+ * @param cb Number of bytes read.
+ */
+typedef DECLCALLBACK(int) FNIOMIOPORTIN(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
+/** Pointer to a FNIOMIOPORTIN(). */
+typedef FNIOMIOPORTIN *PFNIOMIOPORTIN;
+
+/**
+ * Port I/O Handler for string IN operations.
+ *
+ * @returns VINF_SUCCESS or VINF_EM_*.
+ * @returns VERR_IOM_IOPORT_UNUSED if the port is really unused and a ~0 value should be returned.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param uPort Port number used for the IN operation.
+ * @param pGCPtrDst Pointer to the destination buffer (GC, incremented appropriately).
+ * @param pcTransfers Pointer to the number of transfer units to read, on return remaining transfer units.
+ * @param cb Size of the transfer unit (1, 2 or 4 bytes).
+ */
+typedef DECLCALLBACK(int) FNIOMIOPORTINSTRING(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrDst, PRTGCUINTREG pcTransfers, unsigned cb);
+/** Pointer to a FNIOMIOPORTINSTRING(). */
+typedef FNIOMIOPORTINSTRING *PFNIOMIOPORTINSTRING;
+
+/**
+ * Port I/O Handler for OUT operations.
+ *
+ * @returns VINF_SUCCESS or VINF_EM_*.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param uPort Port number used for the OUT operation.
+ * @param u32 The value to output.
+ * @param cb The value size in bytes.
+ */
+typedef DECLCALLBACK(int) FNIOMIOPORTOUT(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
+/** Pointer to a FNIOMIOPORTOUT(). */
+typedef FNIOMIOPORTOUT *PFNIOMIOPORTOUT;
+
+/**
+ * Port I/O Handler for string OUT operations.
+ *
+ * @returns VINF_SUCCESS or VINF_EM_*.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param uPort Port number used for the OUT operation.
+ * @param pGCPtrSrc Pointer to the source buffer (GC, incremented appropriately).
+ * @param pcTransfers Pointer to the number of transfer units to write, on return remaining transfer units.
+ * @param cb Size of the transfer unit (1, 2 or 4 bytes).
+ */
+typedef DECLCALLBACK(int) FNIOMIOPORTOUTSTRING(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, RTGCPTR *pGCPtrSrc, PRTGCUINTREG pcTransfers, unsigned cb);
+/** Pointer to a FNIOMIOPORTOUTSTRING(). */
+typedef FNIOMIOPORTOUTSTRING *PFNIOMIOPORTOUTSTRING;
+
+
+/**
+ * Memory mapped I/O Handler for read operations.
+ *
+ * @returns VBox status code.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param GCPhysAddr Physical address (in GC) where the read starts.
+ * @param pv Where to store the result.
+ * @param cb Number of bytes read.
+ */
+typedef DECLCALLBACK(int) FNIOMMMIOREAD(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb);
+/** Pointer to a FNIOMMMIOREAD(). */
+typedef FNIOMMMIOREAD *PFNIOMMMIOREAD;
+
+/**
+ * Port I/O Handler for write operations.
+ *
+ * @returns VBox status code.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param GCPhysAddr Physical address (in GC) where the read starts.
+ * @param pv Where to fetch the result.
+ * @param cb Number of bytes to write.
+ */
+typedef DECLCALLBACK(int) FNIOMMMIOWRITE(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void const *pv, unsigned cb);
+/** Pointer to a FNIOMMMIOWRITE(). */
+typedef FNIOMMMIOWRITE *PFNIOMMMIOWRITE;
+
+/**
+ * Port I/O Handler for memset operations, actually for REP STOS* instructions handling.
+ *
+ * @returns VBox status code.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param GCPhysAddr Physical address (in GC) where the write starts.
+ * @param u32Item Byte/Word/Dword data to fill.
+ * @param cbItem Size of data in u32Item parameter, restricted to 1/2/4 bytes.
+ * @param cItems Number of iterations.
+ */
+typedef DECLCALLBACK(int) FNIOMMMIOFILL(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, uint32_t u32Item, unsigned cbItem, unsigned cItems);
+/** Pointer to a FNIOMMMIOFILL(). */
+typedef FNIOMMMIOFILL *PFNIOMMMIOFILL;
+
+VMMDECL(VBOXSTRICTRC) IOMIOPortRead(PVM pVM, RTIOPORT Port, uint32_t *pu32Value, size_t cbValue);
+VMMDECL(VBOXSTRICTRC) IOMIOPortWrite(PVM pVM, RTIOPORT Port, uint32_t u32Value, size_t cbValue);
+VMMDECL(VBOXSTRICTRC) IOMInterpretOUT(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
+VMMDECL(VBOXSTRICTRC) IOMInterpretIN(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
+VMMDECL(VBOXSTRICTRC) IOMIOPortReadString(PVM pVM, RTIOPORT Port, PRTGCPTR pGCPtrDst, PRTGCUINTREG pcTransfers, unsigned cb);
+VMMDECL(VBOXSTRICTRC) IOMIOPortWriteString(PVM pVM, RTIOPORT Port, PRTGCPTR pGCPtrSrc, PRTGCUINTREG pcTransfers, unsigned cb);
+VMMDECL(VBOXSTRICTRC) IOMInterpretINS(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
+VMMDECL(VBOXSTRICTRC) IOMInterpretINSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer);
+VMMDECL(VBOXSTRICTRC) IOMInterpretOUTS(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
+VMMDECL(VBOXSTRICTRC) IOMInterpretOUTSEx(PVM pVM, PCPUMCTXCORE pRegFrame, uint32_t uPort, uint32_t uPrefix, DISCPUMODE enmAddrMode, uint32_t cbTransfer);
+VMMDECL(VBOXSTRICTRC) IOMMMIORead(PVM pVM, RTGCPHYS GCPhys, uint32_t *pu32Value, size_t cbValue);
+VMMDECL(VBOXSTRICTRC) IOMMMIOWrite(PVM pVM, RTGCPHYS GCPhys, uint32_t u32Value, size_t cbValue);
+VMMDECL(VBOXSTRICTRC) IOMMMIOPhysHandler(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pCtxCore, RTGCPHYS GCPhysFault);
+VMMDECL(VBOXSTRICTRC) IOMInterpretCheckPortIOAccess(PVM pVM, PCPUMCTXCORE pCtxCore, RTIOPORT Port, unsigned cb);
+VMMDECL(int) IOMMMIOMapMMIO2Page(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysRemapped, uint64_t fPageFlags);
+VMMDECL(int) IOMMMIOMapMMIOHCPage(PVM pVM, RTGCPHYS GCPhys, RTHCPHYS HCPhys, uint64_t fPageFlags);
+VMMDECL(int) IOMMMIOResetRegion(PVM pVM, RTGCPHYS GCPhys);
+VMMDECL(bool) IOMIsLockOwner(PVM pVM);
+
+#ifdef IN_RC
+/** @defgroup grp_iom_rc The IOM Raw-Mode Context API
+ * @ingroup grp_iom
+ * @{
+ */
+VMMRCDECL(VBOXSTRICTRC) IOMRCIOPortHandler(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
+/** @} */
+#endif /* IN_RC */
+
+
+
+#ifdef IN_RING3
+/** @defgroup grp_iom_r3 The IOM Host Context Ring-3 API
+ * @ingroup grp_iom
+ * @{
+ */
+VMMR3_INT_DECL(int) IOMR3Init(PVM pVM);
+VMMR3_INT_DECL(void) IOMR3Reset(PVM pVM);
+VMMR3_INT_DECL(void) IOMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3_INT_DECL(int) IOMR3Term(PVM pVM);
+VMMR3_INT_DECL(int) IOMR3IOPortRegisterR3(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTHCPTR pvUser,
+ R3PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, R3PTRTYPE(PFNIOMIOPORTIN) pfnInCallback,
+ R3PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStringCallback, R3PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStringCallback,
+ const char *pszDesc);
+VMMR3_INT_DECL(int) IOMR3IOPortRegisterRC(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTRCPTR pvUser,
+ RCPTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, RCPTRTYPE(PFNIOMIOPORTIN) pfnInCallback,
+ RCPTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, RCPTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback,
+ const char *pszDesc);
+VMMR3_INT_DECL(int) IOMR3IOPortRegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts, RTR0PTR pvUser,
+ R0PTRTYPE(PFNIOMIOPORTOUT) pfnOutCallback, R0PTRTYPE(PFNIOMIOPORTIN) pfnInCallback,
+ R0PTRTYPE(PFNIOMIOPORTOUTSTRING) pfnOutStrCallback, R0PTRTYPE(PFNIOMIOPORTINSTRING) pfnInStrCallback,
+ const char *pszDesc);
+VMMR3_INT_DECL(int) IOMR3IOPortDeregister(PVM pVM, PPDMDEVINS pDevIns, RTIOPORT PortStart, RTUINT cPorts);
+
+VMMR3_INT_DECL(int) IOMR3MmioRegisterR3(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTHCPTR pvUser,
+ R3PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback,
+ R3PTRTYPE(PFNIOMMMIOREAD) pfnReadCallback,
+ R3PTRTYPE(PFNIOMMMIOFILL) pfnFillCallback,
+ uint32_t fFlags, const char *pszDesc);
+VMMR3_INT_DECL(int) IOMR3MmioRegisterR0(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTR0PTR pvUser,
+ R0PTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback,
+ R0PTRTYPE(PFNIOMMMIOREAD) pfnReadCallback,
+ R0PTRTYPE(PFNIOMMMIOFILL) pfnFillCallback);
+VMMR3_INT_DECL(int) IOMR3MmioRegisterRC(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTGCPTR pvUser,
+ RCPTRTYPE(PFNIOMMMIOWRITE) pfnWriteCallback,
+ RCPTRTYPE(PFNIOMMMIOREAD) pfnReadCallback,
+ RCPTRTYPE(PFNIOMMMIOFILL) pfnFillCallback);
+VMMR3_INT_DECL(int) IOMR3MmioDeregister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange);
+
+/** @} */
+#endif /* IN_RING3 */
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/mm.h b/include/VBox/vmm/mm.h
new file mode 100644
index 00000000..66490fce
--- /dev/null
+++ b/include/VBox/vmm/mm.h
@@ -0,0 +1,370 @@
+/** @file
+ * MM - The Memory Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_mm_h
+#define ___VBox_vmm_mm_h
+
+#include <VBox/types.h>
+#include <iprt/x86.h>
+#include <VBox/sup.h>
+#include <iprt/stdarg.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_mm The Memory Manager API
+ * @{
+ */
+
+/**
+ * Memory Allocation Tags.
+ * For use with MMHyperAlloc(), MMR3HeapAlloc(), MMR3HeapAllocEx(),
+ * MMR3HeapAllocZ() and MMR3HeapAllocZEx().
+ *
+ * @remark Don't forget to update the dump command in MMHeap.cpp!
+ */
+typedef enum MMTAG
+{
+ MM_TAG_INVALID = 0,
+
+ MM_TAG_CFGM,
+ MM_TAG_CFGM_BYTES,
+ MM_TAG_CFGM_STRING,
+ MM_TAG_CFGM_USER,
+
+ MM_TAG_CSAM,
+ MM_TAG_CSAM_PATCH,
+
+ MM_TAG_CPUM_CTX,
+
+ MM_TAG_DBGF,
+ MM_TAG_DBGF_AS,
+ MM_TAG_DBGF_CORE_WRITE,
+ MM_TAG_DBGF_INFO,
+ MM_TAG_DBGF_LINE,
+ MM_TAG_DBGF_LINE_DUP,
+ MM_TAG_DBGF_MODULE,
+ MM_TAG_DBGF_OS,
+ MM_TAG_DBGF_REG,
+ MM_TAG_DBGF_STACK,
+ MM_TAG_DBGF_SYMBOL,
+ MM_TAG_DBGF_SYMBOL_DUP,
+
+ MM_TAG_EM,
+
+ MM_TAG_IOM,
+ MM_TAG_IOM_STATS,
+
+ MM_TAG_MM,
+ MM_TAG_MM_LOOKUP_GUEST,
+ MM_TAG_MM_LOOKUP_PHYS,
+ MM_TAG_MM_LOOKUP_VIRT,
+ MM_TAG_MM_PAGE,
+
+ MM_TAG_PARAV,
+
+ MM_TAG_PATM,
+ MM_TAG_PATM_PATCH,
+
+ MM_TAG_PDM,
+ MM_TAG_PDM_ASYNC_COMPLETION,
+ MM_TAG_PDM_DEVICE,
+ MM_TAG_PDM_DEVICE_DESC,
+ MM_TAG_PDM_DEVICE_USER,
+ MM_TAG_PDM_DRIVER,
+ MM_TAG_PDM_DRIVER_DESC,
+ MM_TAG_PDM_DRIVER_USER,
+ MM_TAG_PDM_USB,
+ MM_TAG_PDM_USB_DESC,
+ MM_TAG_PDM_USB_USER,
+ MM_TAG_PDM_LUN,
+#ifdef VBOX_WITH_NETSHAPER
+ MM_TAG_PDM_NET_SHAPER,
+#endif /* VBOX_WITH_NETSHAPER */
+ MM_TAG_PDM_QUEUE,
+ MM_TAG_PDM_THREAD,
+
+ MM_TAG_PGM,
+ MM_TAG_PGM_CHUNK_MAPPING,
+ MM_TAG_PGM_HANDLERS,
+ MM_TAG_PGM_MAPPINGS,
+ MM_TAG_PGM_PHYS,
+ MM_TAG_PGM_POOL,
+
+ MM_TAG_REM,
+
+ MM_TAG_SELM,
+
+ MM_TAG_SSM,
+
+ MM_TAG_STAM,
+
+ MM_TAG_TM,
+
+ MM_TAG_TRPM,
+
+ MM_TAG_VM,
+ MM_TAG_VM_REQ,
+
+ MM_TAG_VMM,
+
+ MM_TAG_HWACCM,
+
+ MM_TAG_32BIT_HACK = 0x7fffffff
+} MMTAG;
+
+
+
+
+/** @defgroup grp_mm_hyper Hypervisor Memory Management
+ * @ingroup grp_mm
+ * @{ */
+
+VMMDECL(RTR3PTR) MMHyperR0ToR3(PVM pVM, RTR0PTR R0Ptr);
+VMMDECL(RTRCPTR) MMHyperR0ToRC(PVM pVM, RTR0PTR R0Ptr);
+#ifndef IN_RING0
+VMMDECL(void *) MMHyperR0ToCC(PVM pVM, RTR0PTR R0Ptr);
+#endif
+VMMDECL(RTR0PTR) MMHyperR3ToR0(PVM pVM, RTR3PTR R3Ptr);
+VMMDECL(RTRCPTR) MMHyperR3ToRC(PVM pVM, RTR3PTR R3Ptr);
+VMMDECL(RTR3PTR) MMHyperRCToR3(PVM pVM, RTRCPTR RCPtr);
+VMMDECL(RTR0PTR) MMHyperRCToR0(PVM pVM, RTRCPTR RCPtr);
+
+#ifndef IN_RING3
+VMMDECL(void *) MMHyperR3ToCC(PVM pVM, RTR3PTR R3Ptr);
+#else
+DECLINLINE(void *) MMHyperR3ToCC(PVM pVM, RTR3PTR R3Ptr)
+{
+ NOREF(pVM);
+ return R3Ptr;
+}
+#endif
+
+
+#ifndef IN_RC
+VMMDECL(void *) MMHyperRCToCC(PVM pVM, RTRCPTR RCPtr);
+#else
+DECLINLINE(void *) MMHyperRCToCC(PVM pVM, RTRCPTR RCPtr)
+{
+ NOREF(pVM);
+ return (void *)RCPtr;
+}
+#endif
+
+#ifndef IN_RING3
+VMMDECL(RTR3PTR) MMHyperCCToR3(PVM pVM, void *pv);
+#else
+DECLINLINE(RTR3PTR) MMHyperCCToR3(PVM pVM, void *pv)
+{
+ NOREF(pVM);
+ return pv;
+}
+#endif
+
+#ifndef IN_RING0
+VMMDECL(RTR0PTR) MMHyperCCToR0(PVM pVM, void *pv);
+#else
+DECLINLINE(RTR0PTR) MMHyperCCToR0(PVM pVM, void *pv)
+{
+ NOREF(pVM);
+ return pv;
+}
+#endif
+
+#ifndef IN_RC
+VMMDECL(RTRCPTR) MMHyperCCToRC(PVM pVM, void *pv);
+#else
+DECLINLINE(RTRCPTR) MMHyperCCToRC(PVM pVM, void *pv)
+{
+ NOREF(pVM);
+ return (RTRCPTR)pv;
+}
+#endif
+
+
+VMMDECL(int) MMHyperAlloc(PVM pVM, size_t cb, uint32_t uAlignment, MMTAG enmTag, void **ppv);
+VMMDECL(int) MMHyperFree(PVM pVM, void *pv);
+VMMDECL(void) MMHyperHeapCheck(PVM pVM);
+VMMDECL(int) MMR3LockCall(PVM pVM);
+#ifdef DEBUG
+VMMDECL(void) MMHyperHeapDump(PVM pVM);
+#endif
+VMMDECL(size_t) MMHyperHeapGetFreeSize(PVM pVM);
+VMMDECL(size_t) MMHyperHeapGetSize(PVM pVM);
+VMMDECL(RTGCPTR) MMHyperGetArea(PVM pVM, size_t *pcb);
+VMMDECL(bool) MMHyperIsInsideArea(PVM pVM, RTGCPTR GCPtr);
+
+
+VMMDECL(RTHCPHYS) MMPage2Phys(PVM pVM, void *pvPage);
+VMMDECL(void *) MMPagePhys2Page(PVM pVM, RTHCPHYS HCPhysPage);
+VMMDECL(int) MMPagePhys2PageEx(PVM pVM, RTHCPHYS HCPhysPage, void **ppvPage);
+VMMDECL(int) MMPagePhys2PageTry(PVM pVM, RTHCPHYS HCPhysPage, void **ppvPage);
+
+
+/** @def MMHYPER_RC_ASSERT_RCPTR
+ * Asserts that an address is either NULL or inside the hypervisor memory area.
+ * This assertion only works while IN_RC, it's a NOP everywhere else.
+ * @thread The Emulation Thread.
+ */
+#ifdef IN_RC
+# define MMHYPER_RC_ASSERT_RCPTR(pVM, RCPtr) Assert(MMHyperIsInsideArea((pVM), (RTRCUINTPTR)(RCPtr)) || !(RCPtr))
+#else
+# define MMHYPER_RC_ASSERT_RCPTR(pVM, RCPtr) do { } while (0)
+#endif
+
+/** @} */
+
+
+#ifdef IN_RING3
+/** @defgroup grp_mm_r3 The MM Host Context Ring-3 API
+ * @ingroup grp_mm
+ * @{
+ */
+
+VMMR3DECL(int) MMR3InitUVM(PUVM pUVM);
+VMMR3DECL(int) MMR3Init(PVM pVM);
+VMMR3DECL(int) MMR3InitPaging(PVM pVM);
+VMMR3DECL(int) MMR3HyperInitFinalize(PVM pVM);
+VMMR3DECL(int) MMR3Term(PVM pVM);
+VMMR3DECL(void) MMR3TermUVM(PUVM pUVM);
+VMMR3DECL(int) MMR3ReserveHandyPages(PVM pVM, uint32_t cHandyPages);
+VMMR3DECL(int) MMR3IncreaseBaseReservation(PVM pVM, uint64_t cAddBasePages);
+VMMR3DECL(int) MMR3AdjustFixedReservation(PVM pVM, int32_t cDeltaFixedPages, const char *pszDesc);
+VMMR3DECL(int) MMR3UpdateShadowReservation(PVM pVM, uint32_t cShadowPages);
+
+VMMR3DECL(int) MMR3HCPhys2HCVirt(PVM pVM, RTHCPHYS HCPhys, void **ppv);
+
+/** @defgroup grp_mm_r3_hyper Hypervisor Memory Manager (HC R3 Portion)
+ * @ingroup grp_mm_r3
+ * @{ */
+VMMR3DECL(int) MMR3HyperAllocOnceNoRel(PVM pVM, size_t cb, uint32_t uAlignment, MMTAG enmTag, void **ppv);
+VMMR3DECL(int) MMR3HyperAllocOnceNoRelEx(PVM pVM, size_t cb, uint32_t uAlignment, MMTAG enmTag, uint32_t fFlags, void **ppv);
+/** @name MMR3HyperAllocOnceNoRelEx flags
+ * @{ */
+/** Must have kernel mapping.
+ * If not specified, the R0 pointer may point to the user process mapping. */
+#define MMHYPER_AONR_FLAGS_KERNEL_MAPPING RT_BIT(0)
+/** @} */
+VMMR3DECL(int) MMR3HyperSetGuard(PVM pVM, void *pvStart, size_t cb, bool fSet);
+VMMR3DECL(int) MMR3HyperMapHCPhys(PVM pVM, void *pvR3, RTR0PTR pvR0, RTHCPHYS HCPhys, size_t cb, const char *pszDesc, PRTGCPTR pGCPtr);
+VMMR3DECL(int) MMR3HyperMapGCPhys(PVM pVM, RTGCPHYS GCPhys, size_t cb, const char *pszDesc, PRTGCPTR pGCPtr);
+VMMR3DECL(int) MMR3HyperMapMMIO2(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb, const char *pszDesc, PRTRCPTR pRCPtr);
+VMMR3DECL(int) MMR3HyperMapPages(PVM pVM, void *pvR3, RTR0PTR pvR0, size_t cPages, PCSUPPAGE paPages, const char *pszDesc, PRTGCPTR pGCPtr);
+VMMR3DECL(int) MMR3HyperReserve(PVM pVM, unsigned cb, const char *pszDesc, PRTGCPTR pGCPtr);
+VMMR3DECL(RTHCPHYS) MMR3HyperHCVirt2HCPhys(PVM pVM, void *pvHC);
+VMMR3DECL(int) MMR3HyperHCVirt2HCPhysEx(PVM pVM, void *pvHC, PRTHCPHYS pHCPhys);
+VMMR3DECL(void *) MMR3HyperHCPhys2HCVirt(PVM pVM, RTHCPHYS HCPhys);
+VMMR3DECL(int) MMR3HyperHCPhys2HCVirtEx(PVM pVM, RTHCPHYS HCPhys, void **ppv);
+VMMR3_INT_DECL(int) MMR3HyperQueryInfoFromHCPhys(PVM pVM, RTHCPHYS HCPhys, char *pszWhat, size_t cbWhat, uint32_t *pcbAlloc);
+VMMR3DECL(int) MMR3HyperReadGCVirt(PVM pVM, void *pvDst, RTGCPTR GCPtr, size_t cb);
+/** @} */
+
+
+/** @defgroup grp_mm_phys Guest Physical Memory Manager
+ * @todo retire this group, elimintating or moving MMR3PhysGetRamSize to PGMPhys.
+ * @ingroup grp_mm_r3
+ * @{ */
+VMMR3DECL(uint64_t) MMR3PhysGetRamSize(PVM pVM);
+/** @} */
+
+
+/** @defgroup grp_mm_page Physical Page Pool
+ * @ingroup grp_mm_r3
+ * @{ */
+VMMR3DECL(void *) MMR3PageAlloc(PVM pVM);
+VMMR3DECL(RTHCPHYS) MMR3PageAllocPhys(PVM pVM);
+VMMR3DECL(void) MMR3PageFree(PVM pVM, void *pvPage);
+VMMR3DECL(void *) MMR3PageAllocLow(PVM pVM);
+VMMR3DECL(void) MMR3PageFreeLow(PVM pVM, void *pvPage);
+VMMR3DECL(void) MMR3PageFreeByPhys(PVM pVM, RTHCPHYS HCPhysPage);
+VMMR3DECL(void *) MMR3PageDummyHCPtr(PVM pVM);
+VMMR3DECL(RTHCPHYS) MMR3PageDummyHCPhys(PVM pVM);
+/** @} */
+
+
+/** @defgroup grp_mm_heap Heap Manager
+ * @ingroup grp_mm_r3
+ * @{ */
+VMMR3DECL(void *) MMR3HeapAlloc(PVM pVM, MMTAG enmTag, size_t cbSize);
+VMMR3DECL(void *) MMR3HeapAllocU(PUVM pUVM, MMTAG enmTag, size_t cbSize);
+VMMR3DECL(int) MMR3HeapAllocEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv);
+VMMR3DECL(int) MMR3HeapAllocExU(PUVM pUVM, MMTAG enmTag, size_t cbSize, void **ppv);
+VMMR3DECL(void *) MMR3HeapAllocZ(PVM pVM, MMTAG enmTag, size_t cbSize);
+VMMR3DECL(void *) MMR3HeapAllocZU(PUVM pUVM, MMTAG enmTag, size_t cbSize);
+VMMR3DECL(int) MMR3HeapAllocZEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv);
+VMMR3DECL(int) MMR3HeapAllocZExU(PUVM pUVM, MMTAG enmTag, size_t cbSize, void **ppv);
+VMMR3DECL(void *) MMR3HeapRealloc(void *pv, size_t cbNewSize);
+VMMR3DECL(char *) MMR3HeapStrDup(PVM pVM, MMTAG enmTag, const char *psz);
+VMMR3DECL(char *) MMR3HeapStrDupU(PUVM pUVM, MMTAG enmTag, const char *psz);
+VMMR3DECL(char *) MMR3HeapAPrintf(PVM pVM, MMTAG enmTag, const char *pszFormat, ...);
+VMMR3DECL(char *) MMR3HeapAPrintfU(PUVM pUVM, MMTAG enmTag, const char *pszFormat, ...);
+VMMR3DECL(char *) MMR3HeapAPrintfV(PVM pVM, MMTAG enmTag, const char *pszFormat, va_list va);
+VMMR3DECL(char *) MMR3HeapAPrintfVU(PUVM pUVM, MMTAG enmTag, const char *pszFormat, va_list va);
+VMMR3DECL(void) MMR3HeapFree(void *pv);
+/** @} */
+
+/** @defgroup grp_mm_heap User-kernel Heap Manager.
+ * @ingroup grp_mm_r3
+ *
+ * The memory is safely accessible from kernel context as well as user land.
+ *
+ * @{ */
+VMMR3DECL(void *) MMR3UkHeapAlloc(PVM pVM, MMTAG enmTag, size_t cbSize, PRTR0PTR pR0Ptr);
+VMMR3DECL(int) MMR3UkHeapAllocEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv, PRTR0PTR pR0Ptr);
+VMMR3DECL(void *) MMR3UkHeapAllocZ(PVM pVM, MMTAG enmTag, size_t cbSize, PRTR0PTR pR0Ptr);
+VMMR3DECL(int) MMR3UkHeapAllocZEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv, PRTR0PTR pR0Ptr);
+VMMR3DECL(void) MMR3UkHeapFree(PVM pVM, void *pv, MMTAG enmTag);
+/** @} */
+
+/** @} */
+#endif /* IN_RING3 */
+
+
+
+#ifdef IN_RC
+/** @defgroup grp_mm_gc The MM Guest Context API
+ * @ingroup grp_mm
+ * @{
+ */
+
+VMMRCDECL(void) MMGCRamRegisterTrapHandler(PVM pVM);
+VMMRCDECL(void) MMGCRamDeregisterTrapHandler(PVM pVM);
+VMMRCDECL(int) MMGCRamReadNoTrapHandler(void *pDst, void *pSrc, size_t cb);
+/**
+ * @deprecated Don't use this as it doesn't check the page state.
+ */
+VMMRCDECL(int) MMGCRamWriteNoTrapHandler(void *pDst, void *pSrc, size_t cb);
+VMMRCDECL(int) MMGCRamRead(PVM pVM, void *pDst, void *pSrc, size_t cb);
+VMMRCDECL(int) MMGCRamWrite(PVM pVM, void *pDst, void *pSrc, size_t cb);
+
+/** @} */
+#endif /* IN_RC */
+
+/** @} */
+RT_C_DECLS_END
+
+
+#endif
+
diff --git a/include/VBox/vmm/patm.h b/include/VBox/vmm/patm.h
new file mode 100644
index 00000000..70b7fa55
--- /dev/null
+++ b/include/VBox/vmm/patm.h
@@ -0,0 +1,672 @@
+/** @file
+ * PATM - Dynamic Guest OS Patching Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_patm_h
+#define ___VBox_vmm_patm_h
+
+#include <VBox/types.h>
+#include <VBox/dis.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_patm The Patch Manager API
+ * @{
+ */
+#define MAX_PATCHES 512
+
+/**
+ * Flags for specifying the type of patch to install with PATMR3InstallPatch
+ * @{
+ */
+#define PATMFL_CODE32 RT_BIT_64(0)
+#define PATMFL_INTHANDLER RT_BIT_64(1)
+#define PATMFL_SYSENTER RT_BIT_64(2)
+#define PATMFL_GUEST_SPECIFIC RT_BIT_64(3)
+#define PATMFL_USER_MODE RT_BIT_64(4)
+#define PATMFL_IDTHANDLER RT_BIT_64(5)
+#define PATMFL_TRAPHANDLER RT_BIT_64(6)
+#define PATMFL_DUPLICATE_FUNCTION RT_BIT_64(7)
+#define PATMFL_REPLACE_FUNCTION_CALL RT_BIT_64(8)
+#define PATMFL_TRAPHANDLER_WITH_ERRORCODE RT_BIT_64(9)
+#define PATMFL_INTHANDLER_WITH_ERRORCODE (PATMFL_TRAPHANDLER_WITH_ERRORCODE)
+#define PATMFL_MMIO_ACCESS RT_BIT_64(10)
+/* no more room -> change PATMInternal.h if more is needed!! */
+
+/*
+ * Flags above 1024 are reserved for internal use!
+ */
+/** @} */
+
+/** Enable to activate sysenter emulation in GC. */
+/* #define PATM_EMULATE_SYSENTER */
+
+/**
+ * Maximum number of cached VGA writes
+ */
+#define MAX_VGA_WRITE_CACHE 64
+
+typedef struct PATMGCSTATE
+{
+ /* Virtual Flags register (IF + more later on) */
+ uint32_t uVMFlags;
+
+ /* Pending PATM actions (internal use only) */
+ uint32_t uPendingAction;
+
+ /* Records the number of times all patches are called (indicating how many exceptions we managed to avoid) */
+ uint32_t uPatchCalls;
+ /* Scratchpad dword */
+ uint32_t uScratch;
+ /* Debugging info */
+ uint32_t uIretEFlags, uIretCS, uIretEIP;
+
+ /* PATM stack pointer */
+ uint32_t Psp;
+
+ /* PATM interrupt flag */
+ uint32_t fPIF;
+ /* PATM inhibit irq address (used by sti) */
+ RTRCPTR GCPtrInhibitInterrupts;
+
+ /* Scratch room for call patch */
+ RTRCPTR GCCallPatchTargetAddr;
+ RTRCPTR GCCallReturnAddr;
+
+ /* Temporary storage for guest registers. */
+ struct
+ {
+ uint32_t uEAX;
+ uint32_t uECX;
+ uint32_t uEDI;
+ uint32_t eFlags;
+ uint32_t uFlags;
+ } Restore;
+} PATMGCSTATE, *PPATMGCSTATE;
+
+typedef struct PATMTRAPREC
+{
+ /* pointer to original guest code instruction (for emulation) */
+ RTRCPTR pNewEIP;
+ /* pointer to the next guest code instruction */
+ RTRCPTR pNextInstr;
+ /* pointer to the corresponding next instruction in the patch block */
+ RTRCPTR pNextPatchInstr;
+} PATMTRAPREC, *PPATMTRAPREC;
+
+
+/**
+ * Translation state (currently patch to GC ptr)
+ */
+typedef enum
+{
+ PATMTRANS_FAILED,
+ PATMTRANS_SAFE, /* Safe translation */
+ PATMTRANS_PATCHSTART, /* Instruction starts a patch block */
+ PATMTRANS_OVERWRITTEN, /* Instruction overwritten by patchjump */
+ PATMTRANS_INHIBITIRQ /* Instruction must be executed due to instruction fusing */
+} PATMTRANSSTATE;
+
+/**
+ * Load virtualized flags.
+ *
+ * This function is called from CPUMRawEnter(). It doesn't have to update the
+ * IF and IOPL eflags bits, the caller will enforce those to set and 0 respectively.
+ *
+ * @param pVM VM handle.
+ * @param pCtxCore The cpu context core.
+ * @see pg_raw
+ */
+VMMDECL(void) PATMRawEnter(PVM pVM, PCPUMCTXCORE pCtxCore);
+
+/**
+ * Restores virtualized flags.
+ *
+ * This function is called from CPUMRawLeave(). It will update the eflags register.
+ *
+ * @param pVM VM handle.
+ * @param pCtxCore The cpu context core.
+ * @param rawRC Raw mode return code
+ * @see @ref pg_raw
+ */
+VMMDECL(void) PATMRawLeave(PVM pVM, PCPUMCTXCORE pCtxCore, int rawRC);
+
+/**
+ * Get the EFLAGS.
+ * This is a worker for CPUMRawGetEFlags().
+ *
+ * @returns The eflags.
+ * @param pVM The VM handle.
+ * @param pCtxCore The context core.
+ */
+VMMDECL(uint32_t) PATMRawGetEFlags(PVM pVM, PCCPUMCTXCORE pCtxCore);
+
+/**
+ * Updates the EFLAGS.
+ * This is a worker for CPUMRawSetEFlags().
+ *
+ * @param pVM The VM handle.
+ * @param pCtxCore The context core.
+ * @param efl The new EFLAGS value.
+ */
+VMMDECL(void) PATMRawSetEFlags(PVM pVM, PCPUMCTXCORE pCtxCore, uint32_t efl);
+
+/**
+ * Returns the guest context pointer of the GC context structure
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ */
+VMMDECL(RCPTRTYPE(PPATMGCSTATE)) PATMQueryGCState(PVM pVM);
+
+/**
+ * Checks whether the GC address is part of our patch region
+ *
+ * @returns true -> yes, false -> no
+ * @param pVM The VM to operate on.
+ * @param pAddr Guest context address
+ */
+VMMDECL(bool) PATMIsPatchGCAddr(PVM pVM, RTRCUINTPTR pAddr);
+
+/**
+ * Check if we must use raw mode (patch code being executed or marked safe for IF=0)
+ *
+ * @param pVM VM handle.
+ * @param pAddrGC Guest context address
+ */
+VMMDECL(bool) PATMShouldUseRawMode(PVM pVM, RTRCPTR pAddrGC);
+
+/**
+ * Query PATM state (enabled/disabled)
+ *
+ * @returns 0 - disabled, 1 - enabled
+ * @param pVM The VM to operate on.
+ */
+#define PATMIsEnabled(pVM) (pVM->fPATMEnabled)
+
+/**
+ * Set parameters for pending MMIO patch operation
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance.
+ * @param GCPhys MMIO physical address
+ * @param pCachedData GC pointer to cached data
+ */
+VMMDECL(int) PATMSetMMIOPatchInfo(PVM pVM, RTGCPHYS GCPhys, RTRCPTR pCachedData);
+
+
+/**
+ * Adds branch pair to the lookup cache of the particular branch instruction
+ *
+ * @returns VBox status
+ * @param pVM The VM to operate on.
+ * @param pJumpTableGC Pointer to branch instruction lookup cache
+ * @param pBranchTarget Original branch target
+ * @param pRelBranchPatch Relative duplicated function address
+ */
+VMMDECL(int) PATMAddBranchToLookupCache(PVM pVM, RTRCPTR pJumpTableGC, RTRCPTR pBranchTarget, RTRCUINTPTR pRelBranchPatch);
+
+
+/**
+ * Checks if the int 3 was caused by a patched instruction
+ *
+ * @returns VBox status
+ *
+ * @param pVM The VM handle.
+ * @param pCtxCore The relevant core context.
+ */
+VMMRCDECL(int) PATMRCHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame);
+
+/**
+ * Checks if the int 3 was caused by a patched instruction
+ *
+ * @returns VBox status
+ *
+ * @param pVM The VM handle.
+ * @param pInstrGC Instruction pointer
+ * @param pOpcode Original instruction opcode (out, optional)
+ * @param pSize Original instruction size (out, optional)
+ */
+VMMDECL(bool) PATMIsInt3Patch(PVM pVM, RTRCPTR pInstrGC, uint32_t *pOpcode, uint32_t *pSize);
+
+
+/**
+ * Checks if the interrupt flag is enabled or not.
+ *
+ * @returns true if it's enabled.
+ * @returns false if it's disabled.
+ *
+ * @param pVM The VM handle.
+ */
+VMMDECL(bool) PATMAreInterruptsEnabled(PVM pVM);
+
+/**
+ * Checks if the interrupt flag is enabled or not.
+ *
+ * @returns true if it's enabled.
+ * @returns false if it's disabled.
+ *
+ * @param pVM The VM handle.
+ * @param pCtxCore CPU context
+ */
+VMMDECL(bool) PATMAreInterruptsEnabledByCtxCore(PVM pVM, PCPUMCTXCORE pCtxCore);
+
+#ifdef PATM_EMULATE_SYSENTER
+/**
+ * Emulate sysenter, sysexit and syscall instructions
+ *
+ * @returns VBox status
+ *
+ * @param pVM The VM handle.
+ * @param pCtxCore The relevant core context.
+ * @param pCpu Disassembly context
+ */
+VMMDECL(int) PATMSysCall(PVM pVM, PCPUMCTXCORE pRegFrame, PDISCPUSTATE pCpu);
+#endif
+
+#ifdef IN_RC
+/** @defgroup grp_patm_gc The Patch Manager API
+ * @ingroup grp_patm
+ * @{
+ */
+
+/**
+ * Checks if the write is located on a page with was patched before.
+ * (if so, then we are not allowed to turn on r/w)
+ *
+ * @returns VBox status
+ * @param pVM The VM to operate on.
+ * @param pRegFrame CPU context
+ * @param GCPtr GC pointer to write address
+ * @param cbWrite Nr of bytes to write
+ *
+ */
+VMMRCDECL(int) PATMGCHandleWriteToPatchPage(PVM pVM, PCPUMCTXCORE pRegFrame, RTRCPTR GCPtr, uint32_t cbWrite);
+
+/**
+ * Checks if the illegal instruction was caused by a patched instruction
+ *
+ * @returns VBox status
+ *
+ * @param pVM The VM handle.
+ * @param pCtxCore The relevant core context.
+ */
+VMMDECL(int) PATMRCHandleIllegalInstrTrap(PVM pVM, PCPUMCTXCORE pRegFrame);
+
+/** @} */
+
+#endif
+
+#ifdef IN_RING3
+/** @defgroup grp_patm_r3 The Patch Manager API
+ * @ingroup grp_patm
+ * @{
+ */
+
+/**
+ * Query PATM state (enabled/disabled)
+ *
+ * @returns 0 - disabled, 1 - enabled
+ * @param pVM The VM to operate on.
+ */
+VMMR3DECL(int) PATMR3IsEnabled(PVM pVM);
+
+/**
+ * Initializes the PATM.
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ */
+VMMR3DECL(int) PATMR3Init(PVM pVM);
+
+/**
+ * Finalizes HMA page attributes.
+ *
+ * @returns VBox status code.
+ * @param pVM The VM handle.
+ */
+VMMR3DECL(int) PATMR3InitFinalize(PVM pVM);
+
+/**
+ * Applies relocations to data and code managed by this
+ * component. This function will be called at init and
+ * whenever the VMM need to relocate it self inside the GC.
+ *
+ * The PATM will update the addresses used by the switcher.
+ *
+ * @param pVM The VM.
+ */
+VMMR3DECL(void) PATMR3Relocate(PVM pVM);
+
+/**
+ * Terminates the PATM.
+ *
+ * Termination means cleaning up and freeing all resources,
+ * the VM it self is at this point powered off or suspended.
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ */
+VMMR3DECL(int) PATMR3Term(PVM pVM);
+
+/**
+ * PATM reset callback.
+ *
+ * @returns VBox status code.
+ * @param pVM The VM which is reset.
+ */
+VMMR3DECL(int) PATMR3Reset(PVM pVM);
+
+/**
+ * Returns the host context pointer and size of the patch memory block
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pcb Size of the patch memory block
+ */
+VMMR3DECL(void *) PATMR3QueryPatchMemHC(PVM pVM, uint32_t *pcb);
+
+/**
+ * Returns the guest context pointer and size of the patch memory block
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pcb Size of the patch memory block
+ */
+VMMR3DECL(RTRCPTR) PATMR3QueryPatchMemGC(PVM pVM, uint32_t *pcb);
+
+/**
+ * Checks whether the GC address is inside a generated patch jump
+ *
+ * @returns true -> yes, false -> no
+ * @param pVM The VM to operate on.
+ * @param pAddr Guest context address
+ * @param pPatchAddr Guest context patch address (if true)
+ */
+VMMR3DECL(bool) PATMR3IsInsidePatchJump(PVM pVM, RTRCPTR pAddr, PRTGCPTR32 pPatchAddr);
+
+
+/**
+ * Returns the GC pointer of the patch for the specified GC address
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pAddrGC Guest context address
+ */
+VMMR3DECL(RTRCPTR) PATMR3QueryPatchGCPtr(PVM pVM, RTRCPTR pAddrGC);
+
+/**
+ * Checks whether the HC address is part of our patch region
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pAddrGC Guest context address
+ */
+VMMR3DECL(bool) PATMR3IsPatchHCAddr(PVM pVM, R3PTRTYPE(uint8_t *) pAddrHC);
+
+/**
+ * Convert a GC patch block pointer to a HC patch pointer
+ *
+ * @returns HC pointer or NULL if it's not a GC patch pointer
+ * @param pVM The VM to operate on.
+ * @param pAddrGC GC pointer
+ */
+VMMR3DECL(R3PTRTYPE(void *)) PATMR3GCPtrToHCPtr(PVM pVM, RTRCPTR pAddrGC);
+
+
+/**
+ * Returns the host context pointer and size of the GC context structure
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ */
+VMMR3DECL(PPATMGCSTATE) PATMR3QueryGCStateHC(PVM pVM);
+
+/**
+ * Handle trap inside patch code
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pCtx CPU context
+ * @param pEip GC pointer of trapping instruction
+ * @param pNewEip GC pointer to new instruction
+ */
+VMMR3DECL(int) PATMR3HandleTrap(PVM pVM, PCPUMCTX pCtx, RTRCPTR pEip, RTGCPTR *ppNewEip);
+
+/**
+ * Handle page-fault in monitored page
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ */
+VMMR3DECL(int) PATMR3HandleMonitoredPage(PVM pVM);
+
+/**
+ * Notifies PATM about a (potential) write to code that has been patched.
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param GCPtr GC pointer to write address
+ * @param cbWrite Nr of bytes to write
+ *
+ */
+VMMR3DECL(int) PATMR3PatchWrite(PVM pVM, RTRCPTR GCPtr, uint32_t cbWrite);
+
+/**
+ * Notify PATM of a page flush
+ *
+ * @returns VBox status code
+ * @param pVM The VM to operate on.
+ * @param addr GC address of the page to flush
+ */
+VMMR3DECL(int) PATMR3FlushPage(PVM pVM, RTRCPTR addr);
+
+/**
+ * Allows or disallow patching of privileged instructions executed by the guest OS
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param fAllowPatching Allow/disallow patching
+ */
+VMMR3DECL(int) PATMR3AllowPatching(PVM pVM, uint32_t fAllowPatching);
+
+/**
+ * Patch privileged instruction at specified location
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pInstr Guest context point to privileged instruction (0:32 flat address)
+ * @param flags Patch flags
+ *
+ * @note returns failure if patching is not allowed or possible
+ */
+VMMR3DECL(int) PATMR3InstallPatch(PVM pVM, RTRCPTR pInstrGC, uint64_t flags);
+
+/**
+ * Gives hint to PATM about supervisor guest instructions
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pInstr Guest context point to privileged instruction
+ * @param flags Patch flags
+ */
+VMMR3DECL(int) PATMR3AddHint(PVM pVM, RTRCPTR pInstrGC, uint32_t flags);
+
+/**
+ * Patch branch target function for call/jump at specified location.
+ * (in responds to a VINF_PATM_DUPLICATE_FUNCTION GC exit reason)
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pCtx Guest context
+ *
+ */
+VMMR3DECL(int) PATMR3DuplicateFunctionRequest(PVM pVM, PCPUMCTX pCtx);
+
+/**
+ * Query the corresponding GC instruction pointer from a pointer inside the patch block itself
+ *
+ * @returns original GC instruction pointer or 0 if not found
+ * @param pVM The VM to operate on.
+ * @param pPatchGC GC address in patch block
+ * @param pEnmState State of the translated address (out)
+ *
+ */
+VMMR3DECL(RTRCPTR) PATMR3PatchToGCPtr(PVM pVM, RTRCPTR pPatchGC, PATMTRANSSTATE *pEnmState);
+
+/**
+ * Converts Guest code GC ptr to Patch code GC ptr (if found)
+ *
+ * @returns corresponding GC pointer in patch block
+ * @param pVM The VM to operate on.
+ * @param pInstrGC Guest context pointer to privileged instruction
+ *
+ */
+VMMR3DECL(RTRCPTR) PATMR3GuestGCPtrToPatchGCPtr(PVM pVM, RCPTRTYPE(uint8_t*) pInstrGC);
+
+/**
+ * Query the opcode of the original code that was overwritten by the 5 bytes patch jump
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pInstrGC GC address of instr
+ * @param pByte opcode byte pointer (OUT)
+ * @returns VBOX error code
+ *
+ */
+VMMR3DECL(int) PATMR3QueryOpcode(PVM pVM, RTRCPTR pInstrGC, uint8_t *pByte);
+VMMR3DECL(int) PATMR3ReadOrgInstr(PVM pVM, RTGCPTR32 GCPtrInstr, uint8_t *pbDst, size_t cbToRead, size_t *pcbRead);
+
+/**
+ * Disable patch for privileged instruction at specified location
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pInstr Guest context point to privileged instruction
+ *
+ * @note returns failure if patching is not allowed or possible
+ *
+ */
+VMMR3DECL(int) PATMR3DisablePatch(PVM pVM, RTRCPTR pInstrGC);
+
+
+/**
+ * Enable patch for privileged instruction at specified location
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pInstr Guest context point to privileged instruction
+ *
+ * @note returns failure if patching is not allowed or possible
+ *
+ */
+VMMR3DECL(int) PATMR3EnablePatch(PVM pVM, RTRCPTR pInstrGC);
+
+
+/**
+ * Remove patch for privileged instruction at specified location
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on.
+ * @param pInstr Guest context point to privileged instruction
+ *
+ * @note returns failure if patching is not allowed or possible
+ *
+ */
+VMMR3DECL(int) PATMR3RemovePatch(PVM pVM, RTRCPTR pInstrGC);
+
+
+/**
+ * Detects it the specified address falls within a 5 byte jump generated for an active patch.
+ * If so, this patch is permanently disabled.
+ *
+ * @param pVM The VM to operate on.
+ * @param pInstrGC Guest context pointer to instruction
+ * @param pConflictGC Guest context pointer to check
+ */
+VMMR3DECL(int) PATMR3DetectConflict(PVM pVM, RTRCPTR pInstrGC, RTRCPTR pConflictGC);
+
+
+/**
+ * Checks if the instructions at the specified address has been patched already.
+ *
+ * @returns boolean, patched or not
+ * @param pVM The VM to operate on.
+ * @param pInstrGC Guest context pointer to instruction
+ */
+VMMR3DECL(bool) PATMR3HasBeenPatched(PVM pVM, RTRCPTR pInstrGC);
+
+
+/**
+ * Install Linux 2.6 spinlock patch
+ *
+ * @returns VBox status code.
+ * @param pVM The VM to operate on
+ * @param pCallAcquireSpinlockGC GC pointer of call instruction
+ * @param cbAcquireSpinlockCall Instruction size
+ *
+ */
+VMMR3DECL(int) PATMInstallSpinlockPatch(PVM pVM, RTRCPTR pCallAcquireSpinlockGC, uint32_t cbAcquireSpinlockCall);
+
+
+/**
+ * Check if supplied call target is the Linux 2.6 spinlock acquire function
+ *
+ * @returns boolean
+ * @param pVM The VM to operate on
+ * @param pCallAcquireSpinlockGC Call target GC address
+ *
+ */
+VMMR3DECL(bool) PATMIsSpinlockAcquire(PVM pVM, RTRCPTR pCallTargetGC);
+
+/**
+ * Check if supplied call target is the Linux 2.6 spinlock release function
+ *
+ * @returns boolean
+ * @param pVM The VM to operate on
+ * @param pCallTargetGC Call target GC address
+ *
+ */
+VMMR3DECL(bool) PATMIsSpinlockRelease(PVM pVM, RTRCPTR pCallTargetGC);
+
+/**
+ * Check if supplied call target is the Linux 2.6 spinlock release function (patched equivalent)
+ *
+ * @returns boolean
+ * @param pVM The VM to operate on
+ * @param pCallTargetGC Call target GC address
+ *
+ */
+VMMR3DECL(bool) PATMIsSpinlockReleasePatch(PVM pVM, RTRCPTR pCallTargetGC);
+
+/** @} */
+#endif
+
+
+/** @} */
+RT_C_DECLS_END
+
+
+#endif
diff --git a/include/VBox/vmm/pdm.h b/include/VBox/vmm/pdm.h
new file mode 100644
index 00000000..ff95ea82
--- /dev/null
+++ b/include/VBox/vmm/pdm.h
@@ -0,0 +1,40 @@
+/** @file
+ * PDM - Pluggable Device Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdm_h
+#define ___VBox_vmm_pdm_h
+
+#include <VBox/vmm/pdmapi.h>
+#include <VBox/vmm/pdmqueue.h>
+#include <VBox/vmm/pdmcritsect.h>
+#include <VBox/vmm/pdmthread.h>
+#include <VBox/vmm/pdmifs.h>
+#include <VBox/vmm/pdmdrv.h>
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/vmm/pdmusb.h>
+#include <VBox/vmm/pdmsrv.h>
+
+#endif
+
diff --git a/include/VBox/vmm/pdmapi.h b/include/VBox/vmm/pdmapi.h
new file mode 100644
index 00000000..1fb8aef6
--- /dev/null
+++ b/include/VBox/vmm/pdmapi.h
@@ -0,0 +1,210 @@
+/** @file
+ * PDM - Pluggable Device Manager, Core API.
+ *
+ * The 'Core API' has been put in a different header because everyone
+ * is currently including pdm.h. So, pdm.h is for including all of the
+ * PDM stuff, while pdmapi.h is for the core stuff.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmapi_h
+#define ___VBox_vmm_pdmapi_h
+
+#include <VBox/vmm/pdmcommon.h>
+#include <VBox/sup.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm The Pluggable Device Manager API
+ * @{
+ */
+
+VMMDECL(int) PDMGetInterrupt(PVMCPU pVCpu, uint8_t *pu8Interrupt);
+VMMDECL(int) PDMIsaSetIrq(PVM pVM, uint8_t u8Irq, uint8_t u8Level, uint32_t uTagSrc);
+VMM_INT_DECL(int) PDMIoApicSetIrq(PVM pVM, uint8_t u8Irq, uint8_t u8Level, uint32_t uTagSrc);
+VMM_INT_DECL(int) PDMIoApicSendMsi(PVM pVM, RTGCPHYS GCAddr, uint32_t uValue, uint32_t uTagSrc);
+VMMDECL(bool) PDMHasIoApic(PVM pVM);
+VMMDECL(int) PDMApicHasPendingIrq(PVM pVM, bool *pfPending);
+VMMDECL(int) PDMApicSetBase(PVM pVM, uint64_t u64Base);
+VMMDECL(int) PDMApicGetBase(PVM pVM, uint64_t *pu64Base);
+VMMDECL(int) PDMApicSetTPR(PVMCPU pVCpu, uint8_t u8TPR);
+VMMDECL(int) PDMApicGetTPR(PVMCPU pVCpu, uint8_t *pu8TPR, bool *pfPending);
+VMMDECL(int) PDMApicWriteMSR(PVM pVM, VMCPUID iCpu, uint32_t u32Reg, uint64_t u64Value);
+VMMDECL(int) PDMApicReadMSR(PVM pVM, VMCPUID iCpu, uint32_t u32Reg, uint64_t *pu64Value);
+VMMDECL(int) PDMVMMDevHeapR3ToGCPhys(PVM pVM, RTR3PTR pv, RTGCPHYS *pGCPhys);
+VMMDECL(bool) PDMVMMDevHeapIsEnabled(PVM pVM);
+
+
+/** @defgroup grp_pdm_r3 The PDM Host Context Ring-3 API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+VMMR3DECL(int) PDMR3InitUVM(PUVM pUVM);
+VMMR3DECL(int) PDMR3LdrLoadVMMR0U(PUVM pUVM);
+VMMR3DECL(int) PDMR3Init(PVM pVM);
+VMMR3DECL(void) PDMR3PowerOn(PVM pVM);
+VMMR3DECL(void) PDMR3ResetCpu(PVMCPU pVCpu);
+VMMR3DECL(void) PDMR3Reset(PVM pVM);
+VMMR3DECL(void) PDMR3Suspend(PVM pVM);
+VMMR3DECL(void) PDMR3Resume(PVM pVM);
+VMMR3DECL(void) PDMR3PowerOff(PVM pVM);
+VMMR3DECL(void) PDMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3DECL(int) PDMR3Term(PVM pVM);
+VMMR3DECL(void) PDMR3TermUVM(PUVM pUVM);
+
+/**
+ * Module enumeration callback function.
+ *
+ * @returns VBox status.
+ * Failure will stop the search and return the return code.
+ * Warnings will be ignored and not returned.
+ * @param pVM VM Handle.
+ * @param pszFilename Module filename.
+ * @param pszName Module name. (short and unique)
+ * @param ImageBase Address where to executable image is loaded.
+ * @param cbImage Size of the executable image.
+ * @param fRC Set if raw-mode context, clear if host context.
+ * @param pvArg User argument.
+ */
+typedef DECLCALLBACK(int) FNPDMR3ENUM(PVM pVM, const char *pszFilename, const char *pszName,
+ RTUINTPTR ImageBase, size_t cbImage, bool fRC, void *pvArg);
+/** Pointer to a FNPDMR3ENUM() function. */
+typedef FNPDMR3ENUM *PFNPDMR3ENUM;
+VMMR3DECL(int) PDMR3LdrEnumModules(PVM pVM, PFNPDMR3ENUM pfnCallback, void *pvArg);
+VMMR3DECL(void) PDMR3LdrRelocateU(PUVM pUVM, RTGCINTPTR offDelta);
+VMMR3DECL(int) PDMR3LdrGetSymbolR3(PVM pVM, const char *pszModule, const char *pszSymbol, void **ppvValue);
+VMMR3DECL(int) PDMR3LdrGetSymbolR0(PVM pVM, const char *pszModule, const char *pszSymbol, PRTR0PTR ppvValue);
+VMMR3DECL(int) PDMR3LdrGetSymbolR0Lazy(PVM pVM, const char *pszModule, const char *pszSearchPath, const char *pszSymbol, PRTR0PTR ppvValue);
+VMMR3DECL(int) PDMR3LdrLoadRC(PVM pVM, const char *pszFilename, const char *pszName);
+VMMR3DECL(int) PDMR3LdrGetSymbolRC(PVM pVM, const char *pszModule, const char *pszSymbol, PRTRCPTR pRCPtrValue);
+VMMR3DECL(int) PDMR3LdrGetSymbolRCLazy(PVM pVM, const char *pszModule, const char *pszSearchPath, const char *pszSymbol, PRTRCPTR pRCPtrValue);
+VMMR3DECL(int) PDMR3LdrQueryRCModFromPC(PVM pVM, RTRCPTR uPC,
+ char *pszModName, size_t cchModName, PRTRCPTR pMod,
+ char *pszNearSym1, size_t cchNearSym1, PRTRCPTR pNearSym1,
+ char *pszNearSym2, size_t cchNearSym2, PRTRCPTR pNearSym2);
+VMMR3DECL(int) PDMR3LdrQueryR0ModFromPC(PVM pVM, RTR0PTR uPC,
+ char *pszModName, size_t cchModName, PRTR0PTR pMod,
+ char *pszNearSym1, size_t cchNearSym1, PRTR0PTR pNearSym1,
+ char *pszNearSym2, size_t cchNearSym2, PRTR0PTR pNearSym2);
+VMMR3DECL(int) PDMR3LdrGetInterfaceSymbols(PVM pVM,
+ void *pvInterface, size_t cbInterface,
+ const char *pszModule, const char *pszSearchPath,
+ const char *pszSymPrefix, const char *pszSymList,
+ bool fRing0OrRC);
+
+VMMR3DECL(int) PDMR3QueryDevice(PVM pVM, const char *pszDevice, unsigned iInstance, PPPDMIBASE ppBase);
+VMMR3DECL(int) PDMR3QueryDeviceLun(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPPDMIBASE ppBase);
+VMMR3DECL(int) PDMR3QueryLun(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, PPPDMIBASE ppBase);
+VMMR3DECL(int) PDMR3QueryDriverOnLun(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, const char *pszDriver,
+ PPPDMIBASE ppBase);
+VMMR3DECL(int) PDMR3DeviceAttach(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, uint32_t fFlags, PPDMIBASE *ppBase);
+VMMR3DECL(int) PDMR3DeviceDetach(PVM pVM, const char *pszDevice, unsigned iInstance, unsigned iLun, uint32_t fFlags);
+VMMR3_INT_DECL(PPDMCRITSECT) PDMR3DevGetCritSect(PVM pVM, PPDMDEVINS pDevIns);
+VMMR3DECL(int) PDMR3DriverAttach(PVM pVM, const char *pszDevice, unsigned iDevIns, unsigned iLun, uint32_t fFlags, PPPDMIBASE ppBase);
+VMMR3DECL(int) PDMR3DriverDetach(PVM pVM, const char *pszDevice, unsigned iDevIns, unsigned iLun,
+ const char *pszDriver, unsigned iOccurance, uint32_t fFlags);
+VMMR3DECL(int) PDMR3DriverReattach(PVM pVM, const char *pszDevice, unsigned iDevIns, unsigned iLun,
+ const char *pszDriver, unsigned iOccurance, uint32_t fFlags, PCFGMNODE pCfg, PPPDMIBASE ppBase);
+VMMR3DECL(void) PDMR3DmaRun(PVM pVM);
+VMMR3DECL(int) PDMR3LockCall(PVM pVM);
+VMMR3DECL(int) PDMR3RegisterVMMDevHeap(PVM pVM, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize);
+VMMR3DECL(int) PDMR3VMMDevHeapAlloc(PVM pVM, unsigned cbSize, RTR3PTR *ppv);
+VMMR3DECL(int) PDMR3VMMDevHeapFree(PVM pVM, RTR3PTR pv);
+VMMR3DECL(int) PDMR3UnregisterVMMDevHeap(PVM pVM, RTGCPHYS GCPhys);
+VMMR3_INT_DECL(int) PDMR3TracingConfig(PVM pVM, const char *pszName, size_t cchName, bool fEnable, bool fApply);
+VMMR3_INT_DECL(bool) PDMR3TracingAreAll(PVM pVM, bool fEnabled);
+VMMR3_INT_DECL(int) PDMR3TracingQueryConfig(PVM pVM, char *pszConfig, size_t cbConfig);
+/** @} */
+
+
+
+/** @defgroup grp_pdm_rc The PDM Raw-Mode Context API
+ * @ingroup grp_pdm
+ * @{
+ */
+/** @} */
+
+
+
+/** @defgroup grp_pdm_r0 The PDM Ring-0 Context API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/**
+ * Request buffer for PDMR0DriverCallReqHandler / VMMR0_DO_PDM_DRIVER_CALL_REQ_HANDLER.
+ * @see PDMR0DriverCallReqHandler.
+ */
+typedef struct PDMDRIVERCALLREQHANDLERREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The driver instance. */
+ PPDMDRVINSR0 pDrvInsR0;
+ /** The operation. */
+ uint32_t uOperation;
+ /** Explicit alignment padding. */
+ uint32_t u32Alignment;
+ /** Optional 64-bit integer argument. */
+ uint64_t u64Arg;
+} PDMDRIVERCALLREQHANDLERREQ;
+/** Pointer to a PDMR0DriverCallReqHandler / VMMR0_DO_PDM_DRIVER_CALL_REQ_HANDLER
+ * request buffer. */
+typedef PDMDRIVERCALLREQHANDLERREQ *PPDMDRIVERCALLREQHANDLERREQ;
+
+VMMR0_INT_DECL(int) PDMR0DriverCallReqHandler(PVM pVM, PPDMDRIVERCALLREQHANDLERREQ pReq);
+
+/**
+ * Request buffer for PDMR0DeviceCallReqHandler / VMMR0_DO_PDM_DEVICE_CALL_REQ_HANDLER.
+ * @see PDMR0DeviceCallReqHandler.
+ */
+typedef struct PDMDEVICECALLREQHANDLERREQ
+{
+ /** The header. */
+ SUPVMMR0REQHDR Hdr;
+ /** The device instance. */
+ PPDMDEVINSR0 pDevInsR0;
+ /** The request handler for the device. */
+ PFNPDMDEVREQHANDLERR0 pfnReqHandlerR0;
+ /** The operation. */
+ uint32_t uOperation;
+ /** Explicit alignment padding. */
+ uint32_t u32Alignment;
+ /** Optional 64-bit integer argument. */
+ uint64_t u64Arg;
+} PDMDEVICECALLREQHANDLERREQ;
+/** Pointer to a PDMR0DeviceCallReqHandler /
+ * VMMR0_DO_PDM_DEVICE_CALL_REQ_HANDLER request buffer. */
+typedef PDMDEVICECALLREQHANDLERREQ *PPDMDEVICECALLREQHANDLERREQ;
+
+VMMR0_INT_DECL(int) PDMR0DeviceCallReqHandler(PVM pVM, PPDMDEVICECALLREQHANDLERREQ pReq);
+
+/** @} */
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif
diff --git a/include/VBox/vmm/pdmasynccompletion.h b/include/VBox/vmm/pdmasynccompletion.h
new file mode 100644
index 00000000..1d1af265
--- /dev/null
+++ b/include/VBox/vmm/pdmasynccompletion.h
@@ -0,0 +1,368 @@
+/** @file
+ * PDM - Pluggable Device Manager, Async I/O Completion.
+ */
+
+/*
+ * Copyright (C) 2007-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmasynccompletion_h
+#define ___VBox_vmm_pdmasynccompletion_h
+
+#include <VBox/types.h>
+#include <VBox/err.h>
+#include <iprt/assert.h>
+#include <iprt/sg.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_async_completion The PDM Async I/O Completion API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/** Pointer to a PDM async completion template handle. */
+typedef struct PDMASYNCCOMPLETIONTEMPLATE *PPDMASYNCCOMPLETIONTEMPLATE;
+/** Pointer to a PDM async completion template handle pointer. */
+typedef PPDMASYNCCOMPLETIONTEMPLATE *PPPDMASYNCCOMPLETIONTEMPLATE;
+
+/** Pointer to a PDM async completion task handle. */
+typedef struct PDMASYNCCOMPLETIONTASK *PPDMASYNCCOMPLETIONTASK;
+/** Pointer to a PDM async completion task handle pointer. */
+typedef PPDMASYNCCOMPLETIONTASK *PPPDMASYNCCOMPLETIONTASK;
+
+/** Pointer to a PDM async completion endpoint handle. */
+typedef struct PDMASYNCCOMPLETIONENDPOINT *PPDMASYNCCOMPLETIONENDPOINT;
+/** Pointer to a PDM async completion endpoint handle pointer. */
+typedef PPDMASYNCCOMPLETIONENDPOINT *PPPDMASYNCCOMPLETIONENDPOINT;
+
+
+/**
+ * Completion callback for devices.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEDEV(PPDMDEVINS pDevIns, void *pvUser, int rc);
+/** Pointer to a FNPDMASYNCCOMPLETEDEV(). */
+typedef FNPDMASYNCCOMPLETEDEV *PFNPDMASYNCCOMPLETEDEV;
+
+
+/**
+ * Completion callback for drivers.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pvTemplateUser User argument given when creating the template.
+ * @param pvUser User argument given during request initiation.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEDRV(PPDMDRVINS pDrvIns, void *pvTemplateUser, void *pvUser, int rc);
+/** Pointer to a FNPDMASYNCCOMPLETEDRV(). */
+typedef FNPDMASYNCCOMPLETEDRV *PFNPDMASYNCCOMPLETEDRV;
+
+
+/**
+ * Completion callback for USB devices.
+ *
+ * @param pUsbIns The USB device instance.
+ * @param pvUser User argument.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEUSB(PPDMUSBINS pUsbIns, void *pvUser, int rc);
+/** Pointer to a FNPDMASYNCCOMPLETEUSB(). */
+typedef FNPDMASYNCCOMPLETEUSB *PFNPDMASYNCCOMPLETEUSB;
+
+
+/**
+ * Completion callback for internal.
+ *
+ * @param pVM Pointer to the shared VM structure.
+ * @param pvUser User argument for the task.
+ * @param pvUser2 User argument for the template.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACK(void) FNPDMASYNCCOMPLETEINT(PVM pVM, void *pvUser, void *pvUser2, int rc);
+/** Pointer to a FNPDMASYNCCOMPLETEINT(). */
+typedef FNPDMASYNCCOMPLETEINT *PFNPDMASYNCCOMPLETEINT;
+
+
+/**
+ * Creates an async completion template for a device instance.
+ *
+ * The template is used when creating new completion tasks.
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pDevIns The device instance.
+ * @param ppTemplate Where to store the template pointer on success.
+ * @param pfnCompleted The completion callback routine.
+ * @param pszDesc Description.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionTemplateCreateDevice(PVM pVM, PPDMDEVINS pDevIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, PFNPDMASYNCCOMPLETEDEV pfnCompleted, const char *pszDesc);
+
+/**
+ * Creates an async completion template for a driver instance.
+ *
+ * The template is used when creating new completion tasks.
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pDrvIns The driver instance.
+ * @param ppTemplate Where to store the template pointer on success.
+ * @param pfnCompleted The completion callback routine.
+ * @param pvTemplateUser Template user argument.
+ * @param pszDesc Description.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionTemplateCreateDriver(PVM pVM, PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser, const char *pszDesc);
+
+/**
+ * Creates an async completion template for a USB device instance.
+ *
+ * The template is used when creating new completion tasks.
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pUsbIns The USB device instance.
+ * @param ppTemplate Where to store the template pointer on success.
+ * @param pfnCompleted The completion callback routine.
+ * @param pszDesc Description.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionTemplateCreateUsb(PVM pVM, PPDMUSBINS pUsbIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, PFNPDMASYNCCOMPLETEUSB pfnCompleted, const char *pszDesc);
+
+/**
+ * Creates an async completion template for internally by the VMM.
+ *
+ * The template is used when creating new completion tasks.
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the shared VM structure.
+ * @param ppTemplate Where to store the template pointer on success.
+ * @param pfnCompleted The completion callback routine.
+ * @param pvUser2 The 2nd user argument for the callback.
+ * @param pszDesc Description.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionTemplateCreateInternal(PVM pVM, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, PFNPDMASYNCCOMPLETEINT pfnCompleted, void *pvUser2, const char *pszDesc);
+
+/**
+ * Destroys the specified async completion template.
+ *
+ * @returns VBox status codes:
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_PDM_ASYNC_TEMPLATE_BUSY if the template is still in use.
+ *
+ * @param pTemplate The template in question.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionTemplateDestroy(PPDMASYNCCOMPLETIONTEMPLATE pTemplate);
+
+/**
+ * Destroys all the specified async completion templates for the given device instance.
+ *
+ * @returns VBox status codes:
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_PDM_ASYNC_TEMPLATE_BUSY if one or more of the templates are still in use.
+ *
+ * @param pVM Pointer to the shared VM structure.
+ * @param pDevIns The device instance.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionTemplateDestroyDevice(PVM pVM, PPDMDEVINS pDevIns);
+
+/**
+ * Destroys all the specified async completion templates for the given driver instance.
+ *
+ * @returns VBox status codes:
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_PDM_ASYNC_TEMPLATE_BUSY if one or more of the templates are still in use.
+ *
+ * @param pVM Pointer to the shared VM structure.
+ * @param pDrvIns The driver instance.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionTemplateDestroyDriver(PVM pVM, PPDMDRVINS pDrvIns);
+
+/**
+ * Destroys all the specified async completion templates for the given USB device instance.
+ *
+ * @returns VBox status codes:
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_PDM_ASYNC_TEMPLATE_BUSY if one or more of the templates are still in use.
+ *
+ * @param pVM Pointer to the shared VM structure.
+ * @param pUsbIns The USB device instance.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionTemplateDestroyUsb(PVM pVM, PPDMUSBINS pUsbIns);
+
+
+/**
+ * Opens a file as an async completion endpoint.
+ *
+ * @returns VBox status code.
+ * @param ppEndpoint Where to store the opaque endpoint handle on success.
+ * @param pszFilename Path to the file which is to be opened. (UTF-8)
+ * @param fFlags Open flags, see grp_pdmacep_file_flags.
+ * @param pTemplate Handle to the completion callback template to use
+ * for this end point.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionEpCreateForFile(PPPDMASYNCCOMPLETIONENDPOINT ppEndpoint,
+ const char *pszFilename, uint32_t fFlags,
+ PPDMASYNCCOMPLETIONTEMPLATE pTemplate);
+
+/** @defgroup grp_pdmacep_file_flags Flags for PDMR3AsyncCompletionEpCreateForFile
+ * @{ */
+/** Open the file in read-only mode. */
+#define PDMACEP_FILE_FLAGS_READ_ONLY RT_BIT_32(0)
+/** Whether the file should not be write protected.
+ * The default is to protect the file against writes by other processes
+ * when opened in read/write mode to prevent data corruption by
+ * concurrent access which can occur if the local writeback cache is enabled.
+ */
+#define PDMACEP_FILE_FLAGS_DONT_LOCK RT_BIT_32(2)
+/** Open the endpoint with the host cache enabled. */
+#define PDMACEP_FILE_FLAGS_HOST_CACHE_ENABLED RT_BIT_32(3)
+/** @} */
+
+/**
+ * Closes a endpoint waiting for any pending tasks to finish.
+ *
+ * @returns nothing.
+ * @param pEndpoint Handle of the endpoint.
+ */
+VMMR3DECL(void) PDMR3AsyncCompletionEpClose(PPDMASYNCCOMPLETIONENDPOINT pEndpoint);
+
+/**
+ * Creates a read task on the given endpoint.
+ *
+ * @returns VBox status code.
+ * @param pEndpoint The file endpoint to read from.
+ * @param off Where to start reading from.
+ * @param paSegments Scatter gather list to store the data in.
+ * @param cSegments Number of segments in the list.
+ * @param cbRead The overall number of bytes to read.
+ * @param pvUser Opaque user data returned in the completion callback
+ * upon completion of the task.
+ * @param ppTask Where to store the task handle on success.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionEpRead(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, RTFOFF off,
+ PCRTSGSEG paSegments, unsigned cSegments,
+ size_t cbRead, void *pvUser,
+ PPPDMASYNCCOMPLETIONTASK ppTask);
+
+/**
+ * Creates a write task on the given endpoint.
+ *
+ * @returns VBox status code.
+ * @param pEndpoint The file endpoint to write to.
+ * @param off Where to start writing at.
+ * @param paSegments Scatter gather list of the data to write.
+ * @param cSegments Number of segments in the list.
+ * @param cbWrite The overall number of bytes to write.
+ * @param pvUser Opaque user data returned in the completion callback
+ * upon completion of the task.
+ * @param ppTask Where to store the task handle on success.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionEpWrite(PPDMASYNCCOMPLETIONENDPOINT pEndpoint, RTFOFF off,
+ PCRTSGSEG paSegments, unsigned cSegments,
+ size_t cbWrite, void *pvUser,
+ PPPDMASYNCCOMPLETIONTASK ppTask);
+
+/**
+ * Creates a flush task on the given endpoint.
+ *
+ * Every read and write task initiated before the flush task is
+ * finished upon completion of this task.
+ *
+ * @returns VBox status code.
+ * @param pEndpoint The file endpoint to flush.
+ * @param pvUser Opaque user data returned in the completion callback
+ * upon completion of the task.
+ * @param ppTask Where to store the task handle on success.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionEpFlush(PPDMASYNCCOMPLETIONENDPOINT pEndpoint,
+ void *pvUser,
+ PPPDMASYNCCOMPLETIONTASK ppTask);
+
+/**
+ * Queries the size of an endpoint.
+ * Not that some endpoints may not support this and will return an error
+ * (sockets for example).
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_SUPPORTED if the endpoint does not support this operation.
+ * @param pEndpoint The file endpoint.
+ * @param pcbSize Where to store the size of the endpoint.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionEpGetSize(PPDMASYNCCOMPLETIONENDPOINT pEndpoint,
+ uint64_t *pcbSize);
+
+/**
+ * Sets the size of an endpoint.
+ * Not that some endpoints may not support this and will return an error
+ * (sockets for example).
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_SUPPORTED if the endpoint does not support this operation.
+ * @param pEndpoint The file endpoint.
+ * @param cbSize The size to set.
+ *
+ * @note PDMR3AsyncCompletionEpFlush should be called before this operation is executed.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionEpSetSize(PPDMASYNCCOMPLETIONENDPOINT pEndpoint,
+ uint64_t cbSize);
+
+/**
+ * Assigns or removes a bandwidth control manager to/from the endpoint.
+ *
+ * @returns VBox status code.
+ * @param pEndpoint The endpoint.
+ * @param pcszBwMgr The identifer of the new bandwidth manager to assign
+ * or NULL to remove the current one.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionEpSetBwMgr(PPDMASYNCCOMPLETIONENDPOINT pEndpoint,
+ const char *pcszBwMgr);
+
+/**
+ * Cancels an async completion task.
+ *
+ * If you want to use this method, you have to take great create to make sure
+ * you will never attempt cancel a task which has been completed. Since there is
+ * no reference counting or anything on the task it self, you have to serialize
+ * the cancelation and completion paths such that the aren't racing one another.
+ *
+ * @returns VBox status code
+ * @param pTask The Task to cancel.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionTaskCancel(PPDMASYNCCOMPLETIONTASK pTask);
+
+/**
+ * Changes the limit of a bandwidth manager for file endpoints to the given value.
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pcszBwMgr The identifer of the bandwidth manager to change.
+ * @param cbMaxNew The new maximum for the bandwidth manager in bytes/sec.
+ */
+VMMR3DECL(int) PDMR3AsyncCompletionBwMgrSetMaxForFile(PVM pVM, const char *pcszBwMgr, uint32_t cbMaxNew);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/pdmasynctask.h b/include/VBox/vmm/pdmasynctask.h
new file mode 100644
index 00000000..65fdd245
--- /dev/null
+++ b/include/VBox/vmm/pdmasynctask.h
@@ -0,0 +1,61 @@
+/** @file
+ * PDM - Pluggable Device Manager, Async Task.
+ */
+
+/*
+ * Copyright (C) 2007-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmasynctask_h
+#define ___VBox_vmm_pdmasynctask_h
+
+#include <VBox/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_async_task The PDM Async Task API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/** Pointer to a PDM async task template handle. */
+typedef struct PDMASYNCTASKTEMPLATE *PPDMASYNCTASKTEMPLATE;
+/** Pointer to a PDM async task template handle pointer. */
+typedef PPDMASYNCTASKTEMPLATE *PPPDMASYNCTASKTEMPLATE;
+
+/** Pointer to a PDM async task handle. */
+typedef struct PDMASYNCTASK *PPDMASYNCTASK;
+/** Pointer to a PDM async task handle pointer. */
+typedef PPDMASYNCTASK *PPPDMASYNCTASK;
+
+/* This should be similar to VMReq, only difference there will be a pool
+ of worker threads instead of EMT. The actual implementation should be
+ made in IPRT so we can reuse it for other stuff later. The reason why
+ it should be put in PDM is because we need to manage it wrt to VM
+ state changes (need exception - add a flag for this). */
+
+/** @} */
+
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/pdmblkcache.h b/include/VBox/vmm/pdmblkcache.h
new file mode 100644
index 00000000..fc92bc4f
--- /dev/null
+++ b/include/VBox/vmm/pdmblkcache.h
@@ -0,0 +1,422 @@
+/** @file
+ * PDM - Pluggable Device Manager, Block cache.
+ */
+
+/*
+ * Copyright (C) 2007-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmblkcache_h
+#define ___VBox_vmm_pdmblkcache_h
+
+#include <VBox/types.h>
+#include <VBox/err.h>
+#include <iprt/assert.h>
+#include <iprt/sg.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_blk_cache The PDM Block Cache API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/** Pointer to a PDM block cache. */
+typedef struct PDMBLKCACHE *PPDMBLKCACHE;
+/** Pointer to a PDM block cache pointer. */
+typedef PPDMBLKCACHE *PPPDMBLKCACHE;
+
+/** I/O transfer handle. */
+typedef struct PDMBLKCACHEIOXFER *PPDMBLKCACHEIOXFER;
+
+/**
+ * Block cache I/O request transfer direction.
+ */
+typedef enum PDMBLKCACHEXFERDIR
+{
+ /** Read */
+ PDMBLKCACHEXFERDIR_READ = 0,
+ /** Write */
+ PDMBLKCACHEXFERDIR_WRITE,
+ /** Flush */
+ PDMBLKCACHEXFERDIR_FLUSH,
+ /** Discard */
+ PDMBLKCACHEXFERDIR_DISCARD
+} PDMBLKCACHEXFERDIR;
+
+/**
+ * Completion callback for drivers.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pvUser User argument given during request initiation.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACK(void) FNPDMBLKCACHEXFERCOMPLETEDRV(PPDMDRVINS pDrvIns, void *pvUser, int rc);
+/** Pointer to a FNPDMBLKCACHEXFERCOMPLETEDRV(). */
+typedef FNPDMBLKCACHEXFERCOMPLETEDRV *PFNPDMBLKCACHEXFERCOMPLETEDRV;
+
+/**
+ * I/O enqueue callback for drivers.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pvUser User argument given during request initiation.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACK(int) FNPDMBLKCACHEXFERENQUEUEDRV(PPDMDRVINS pDrvIns,
+ PDMBLKCACHEXFERDIR enmXferDir,
+ uint64_t off, size_t cbXfer,
+ PCRTSGBUF pcSgBuf, PPDMBLKCACHEIOXFER hIoXfer);
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDRV(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDRV *PFNPDMBLKCACHEXFERENQUEUEDRV;
+
+/**
+ * Discard enqueue callback for drivers.
+ *
+ * @param pDrvIns The driver instance.
+ * @param paRanges Ranges to discard.
+ * @param cRanges Number of range entries.
+ * @param hIoXfer I/O handle to return on completion.
+ */
+typedef DECLCALLBACK(int) FNPDMBLKCACHEXFERENQUEUEDISCARDDRV(PPDMDRVINS pDrvIns,
+ PCRTRANGE paRanges, unsigned cRanges,
+ PPDMBLKCACHEIOXFER hIoXfer);
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDISCARDDRV(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDISCARDDRV *PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV;
+
+/**
+ * Completion callback for devices.
+ *
+ * @param pDrvIns The device instance.
+ * @param pvUser User argument given during request initiation.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACK(void) FNPDMBLKCACHEXFERCOMPLETEDEV(PPDMDEVINS pDevIns, void *pvUser, int rc);
+/** Pointer to a FNPDMBLKCACHEXFERCOMPLETEDEV(). */
+typedef FNPDMBLKCACHEXFERCOMPLETEDEV *PFNPDMBLKCACHEXFERCOMPLETEDEV;
+
+/**
+ * I/O enqueue callback for devices.
+ *
+ * @param pDevIns The device instance.
+ * @param pvUser User argument given during request initiation.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACK(int) FNPDMBLKCACHEXFERENQUEUEDEV(PPDMDEVINS pDevIns,
+ PDMBLKCACHEXFERDIR enmXferDir,
+ uint64_t off, size_t cbXfer,
+ PCRTSGBUF pcSgBuf, PPDMBLKCACHEIOXFER hIoXfer);
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDEV(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDEV *PFNPDMBLKCACHEXFERENQUEUEDEV;
+
+/**
+ * Discard enqueue callback for devices.
+ *
+ * @param pDrvIns The driver instance.
+ * @param paRanges Ranges to discard.
+ * @param cRanges Number of range entries.
+ * @param hIoXfer I/O handle to return on completion.
+ */
+typedef DECLCALLBACK(int) FNPDMBLKCACHEXFERENQUEUEDISCARDDEV(PPDMDEVINS pDevIns,
+ PCRTRANGE paRanges, unsigned cRanges,
+ PPDMBLKCACHEIOXFER hIoXfer);
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDISCARDDEV(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDISCARDDEV *PFNPDMBLKCACHEXFERENQUEUEDISCARDDEV;
+
+/**
+ * Completion callback for drivers.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pvUser User argument given during request initiation.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACK(void) FNPDMBLKCACHEXFERCOMPLETEINT(void *pvUserInt, void *pvUser, int rc);
+/** Pointer to a FNPDMBLKCACHEXFERCOMPLETEINT(). */
+typedef FNPDMBLKCACHEXFERCOMPLETEINT *PFNPDMBLKCACHEXFERCOMPLETEINT;
+
+/**
+ * I/O enqueue callback for drivers.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pvUser User argument given during request initiation.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACK(int) FNPDMBLKCACHEXFERENQUEUEINT(void *pvUser,
+ PDMBLKCACHEXFERDIR enmXferDir,
+ uint64_t off, size_t cbXfer,
+ PCRTSGBUF pcSgBuf, PPDMBLKCACHEIOXFER hIoXfer);
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEINT(). */
+typedef FNPDMBLKCACHEXFERENQUEUEINT *PFNPDMBLKCACHEXFERENQUEUEINT;
+
+/**
+ * Discard enqueue callback for VMM internal users.
+ *
+ * @param pDrvIns The driver instance.
+ * @param paRanges Ranges to discard.
+ * @param cRanges Number of range entries.
+ * @param hIoXfer I/O handle to return on completion.
+ */
+typedef DECLCALLBACK(int) FNPDMBLKCACHEXFERENQUEUEDISCARDINT(void *pvUser,
+ PCRTRANGE paRanges, unsigned cRanges,
+ PPDMBLKCACHEIOXFER hIoXfer);
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDISCARDINT(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDISCARDINT *PFNPDMBLKCACHEXFERENQUEUEDISCARDINT;
+
+/**
+ * Completion callback for USB.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pvUser User argument given during request initiation.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACK(void) FNPDMBLKCACHEXFERCOMPLETEUSB(PPDMUSBINS pUsbIns, void *pvUser, int rc);
+/** Pointer to a FNPDMBLKCACHEXFERCOMPLETEUSB(). */
+typedef FNPDMBLKCACHEXFERCOMPLETEUSB *PFNPDMBLKCACHEXFERCOMPLETEUSB;
+
+/**
+ * I/O enqueue callback for drivers.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pvUser User argument given during request initiation.
+ * @param rc The status code of the completed request.
+ */
+typedef DECLCALLBACK(int) FNPDMBLKCACHEXFERENQUEUEUSB(PPDMUSBINS pUsbIns,
+ PDMBLKCACHEXFERDIR enmXferDir,
+ uint64_t off, size_t cbXfer,
+ PCRTSGBUF pcSgBuf, PPDMBLKCACHEIOXFER hIoXfer);
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEUSB(). */
+typedef FNPDMBLKCACHEXFERENQUEUEUSB *PFNPDMBLKCACHEXFERENQUEUEUSB;
+
+/**
+ * Discard enqueue callback for USB devices.
+ *
+ * @param pUsbIns The USB device instance.
+ * @param paRanges Ranges to discard.
+ * @param cRanges Number of range entries.
+ * @param hIoXfer I/O handle to return on completion.
+ */
+typedef DECLCALLBACK(int) FNPDMBLKCACHEXFERENQUEUEDISCARDUSB(PPDMUSBINS pUsbIns,
+ PCRTRANGE paRanges, unsigned cRanges,
+ PPDMBLKCACHEIOXFER hIoXfer);
+/** Pointer to a FNPDMBLKCACHEXFERENQUEUEDISCARDUSB(). */
+typedef FNPDMBLKCACHEXFERENQUEUEDISCARDUSB *PFNPDMBLKCACHEXFERENQUEUEDISCARDUSB;
+
+/**
+ * Create a block cache user for a driver instance.
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pDrvIns The driver instance.
+ * @param ppBlkCache Where to store the handle to the block cache.
+ * @param pfnXferComplete The I/O transfer complete callback.
+ * @param pfnXferEnqueue The I/O request enqueue callback.
+ * @param pfnXferEnqueueDiscard The discard request enqueue callback.
+ * @param pcszId Unique ID used to identify the user.
+ */
+VMMR3DECL(int) PDMR3BlkCacheRetainDriver(PVM pVM, PPDMDRVINS pDrvIns, PPPDMBLKCACHE ppBlkCache,
+ PFNPDMBLKCACHEXFERCOMPLETEDRV pfnXferComplete,
+ PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue,
+ PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard,
+ const char *pcszId);
+
+/**
+ * Create a block cache user for a device instance.
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pDevIns The device instance.
+ * @param ppBlkCache Where to store the handle to the block cache.
+ * @param pfnXferComplete The I/O transfer complete callback.
+ * @param pfnXferEnqueue The I/O request enqueue callback.
+ * @param pfnXferEnqueueDiscard The discard request enqueue callback.
+ * @param pcszId Unique ID used to identify the user.
+ */
+VMMR3DECL(int) PDMR3BlkCacheRetainDevice(PVM pVM, PPDMDEVINS pDevIns, PPPDMBLKCACHE ppBlkCache,
+ PFNPDMBLKCACHEXFERCOMPLETEDEV pfnXferComplete,
+ PFNPDMBLKCACHEXFERENQUEUEDEV pfnXferEnqueue,
+ PFNPDMBLKCACHEXFERENQUEUEDISCARDDEV pfnXferEnqueueDiscard,
+ const char *pcszId);
+
+/**
+ * Create a block cache user for a USB instance.
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pUsbIns The USB device instance.
+ * @param ppBlkCache Where to store the handle to the block cache.
+ * @param pfnXferComplete The I/O transfer complete callback.
+ * @param pfnXferEnqueue The I/O request enqueue callback.
+ * @param pfnXferEnqueueDiscard The discard request enqueue callback.
+ * @param pcszId Unique ID used to identify the user.
+ */
+VMMR3DECL(int) PDMR3BlkCacheRetainUsb(PVM pVM, PPDMUSBINS pUsbIns, PPPDMBLKCACHE ppBlkCache,
+ PFNPDMBLKCACHEXFERCOMPLETEUSB pfnXferComplete,
+ PFNPDMBLKCACHEXFERENQUEUEUSB pfnXferEnqueue,
+ PFNPDMBLKCACHEXFERENQUEUEDISCARDUSB pfnXferEnqueueDiscard,
+ const char *pcszId);
+
+/**
+ * Create a block cache user for internal use by VMM.
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pvUser Opaque user data.
+ * @param ppBlkCache Where to store the handle to the block cache.
+ * @param pfnXferComplete The I/O transfer complete callback.
+ * @param pfnXferEnqueue The I/O request enqueue callback.
+ * @param pfnXferEnqueueDiscard The discard request enqueue callback.
+ * @param pcszId Unique ID used to identify the user.
+ */
+VMMR3DECL(int) PDMR3BlkCacheRetainInt(PVM pVM, void *pvUser, PPPDMBLKCACHE ppBlkCache,
+ PFNPDMBLKCACHEXFERCOMPLETEINT pfnXferComplete,
+ PFNPDMBLKCACHEXFERENQUEUEINT pfnXferEnqueue,
+ PFNPDMBLKCACHEXFERENQUEUEDISCARDINT pfnXferEnqueueDiscard,
+ const char *pcszId);
+
+/**
+ * Releases a block cache handle.
+ *
+ * @returns nothing.
+ * @param pBlkCache Block cache handle.
+ */
+VMMR3DECL(void) PDMR3BlkCacheRelease(PPDMBLKCACHE pBlkCache);
+
+/**
+ * Releases all block cache handles for a device instance.
+ *
+ * @returns nothing.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pDevIns The device instance.
+ */
+VMMR3DECL(void) PDMR3BlkCacheReleaseDevice(PVM pVM, PPDMDEVINS pDevIns);
+
+/**
+ * Releases all block cache handles for a driver instance.
+ *
+ * @returns nothing.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pDrvIns The driver instance.
+ */
+VMMR3DECL(void) PDMR3BlkCacheReleaseDriver(PVM pVM, PPDMDRVINS pDrvIns);
+
+/**
+ * Releases all block cache handles for a USB device instance.
+ *
+ * @returns nothing.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pUsbIns The USB device instance.
+ */
+VMMR3DECL(void) PDMR3BlkCacheReleaseUsb(PVM pVM, PPDMUSBINS pUsbIns);
+
+/**
+ * Creates a read task on the given endpoint.
+ *
+ * @returns VBox status code.
+ * @param pEndpoint The file endpoint to read from.
+ * @param off Where to start reading from.
+ * @param paSegments Scatter gather list to store the data in.
+ * @param cSegments Number of segments in the list.
+ * @param cbRead The overall number of bytes to read.
+ * @param pvUser Opaque user data returned in the completion callback
+ * upon completion of the read.
+ */
+VMMR3DECL(int) PDMR3BlkCacheRead(PPDMBLKCACHE pBlkCache, uint64_t off,
+ PCRTSGBUF pcSgBuf, size_t cbRead, void *pvUser);
+
+/**
+ * Creates a write task on the given endpoint.
+ *
+ * @returns VBox status code.
+ * @param pEndpoint The file endpoint to write to.
+ * @param off Where to start writing at.
+ * @param paSegments Scatter gather list of the data to write.
+ * @param cSegments Number of segments in the list.
+ * @param cbWrite The overall number of bytes to write.
+ * @param pvUser Opaque user data returned in the completion callback
+ * upon completion of the task.
+ */
+VMMR3DECL(int) PDMR3BlkCacheWrite(PPDMBLKCACHE pBlkCache, uint64_t off,
+ PCRTSGBUF pcSgBuf, size_t cbWrite, void *pvUser);
+
+/**
+ * Creates a flush task on the given endpoint.
+ *
+ * @returns VBox status code.
+ * @param pEndpoint The file endpoint to flush.
+ * @param pvUser Opaque user data returned in the completion callback
+ * upon completion of the task.
+ */
+VMMR3DECL(int) PDMR3BlkCacheFlush(PPDMBLKCACHE pBlkCache, void *pvUser);
+
+/**
+ * Discards the given ranges from the cache.
+ *
+ * @returns VBox status code.
+ * @param pEndpoint The file endpoint to flush.
+ * @param paRanges Array of ranges to discard.
+ * @param cRanges Number of ranges in the array.
+ * @param pvUser Opaque user data returned in the completion callback
+ * upon completion of the task.
+ */
+VMMR3DECL(int) PDMR3BlkCacheDiscard(PPDMBLKCACHE pBlkCache, PCRTRANGE paRanges, unsigned cRanges, void *pvUser);
+
+/**
+ * Notify the cache of a complete I/O transfer.
+ *
+ * @returns nothing.
+ * @param pBlkCache The cache instance.
+ * @param hIoXfer The I/O transfer handle which completed.
+ * @param rcIoXfer The status code of the completed request.
+ */
+VMMR3DECL(void) PDMR3BlkCacheIoXferComplete(PPDMBLKCACHE pBlkCache, PPDMBLKCACHEIOXFER hIoXfer, int rcIoXfer);
+
+/**
+ * Suspends the block cache. The cache waits until all I/O transfers completed
+ * and stops to enqueue new requests after the call returned but will not accept
+ * reads, write or flushes either.
+ *
+ * @returns VBox status code.
+ * @param pBlkCache The cache instance.
+ */
+VMMR3DECL(int) PDMR3BlkCacheSuspend(PPDMBLKCACHE pBlkCache);
+
+/**
+ * Resumes operation of the block cache.
+ *
+ * @returns VBox status code.
+ * @param pBlkCache The cache instance.
+ */
+VMMR3DECL(int) PDMR3BlkCacheResume(PPDMBLKCACHE pBlkCache);
+
+/**
+ * Clears the block cache and removes all entries. The cache waits until all
+ * I/O transfers completed.
+ *
+ * @returns VBox status code.
+ * @param pBlkCache The cache instance.
+ */
+VMMR3DECL(int) PDMR3BlkCacheClear(PPDMBLKCACHE pBlkCache);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/pdmcardreaderinfs.h b/include/VBox/vmm/pdmcardreaderinfs.h
new file mode 100644
index 00000000..e1ad5a2d
--- /dev/null
+++ b/include/VBox/vmm/pdmcardreaderinfs.h
@@ -0,0 +1,116 @@
+/* $Id: pdmcardreaderinfs.h $ */
+
+/** @file
+ * cardreaderinfs - interface between Usb Card Reader device and its driver.
+ */
+
+/*
+ * Copyright (C) 2011-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmcardreaderinfs_h
+# define ___VBox_vmm_pdmcardreaderinfs_h
+
+#include <VBox/types.h>
+
+#define PDMICARDREADERDOWN_IID "78d65378-889c-4418-8bc2-7a89a5af2817"
+
+typedef struct PDMICARDREADER_IO_REQUEST
+{
+ uint32_t u32Protocol; /* Protocol identifier */
+ uint32_t cbPciLength; /* Protocol Control Information Length */
+ /* 'cbPciLength - 8' bytes of control info may follow. */
+} PDMICARDREADER_IO_REQUEST;
+
+typedef struct PDMICARDREADER_READERSTATE
+{
+ char *pszReaderName;
+ uint32_t u32CurrentState; /* Current state of reader at time of call. */
+ uint32_t u32EventState; /* State of reader after state change */
+ uint32_t cbAtr; /* Number of bytes in the returned ATR. */
+ uint8_t au8Atr[36]; /* Atr of inserted card, (extra alignment bytes) */
+} PDMICARDREADER_READERSTATE;
+
+
+typedef struct PDMICARDREADERDOWN PDMICARDREADERDOWN;
+typedef PDMICARDREADERDOWN *PPDMICARDREADERDOWN;
+struct PDMICARDREADERDOWN
+{
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderDownEstablishContext,(PPDMICARDREADERDOWN pInterface));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderDownConnect,(PPDMICARDREADERDOWN pInterface, void *pvUser, const char *pszCardReaderName,
+ uint32_t u32ShareMode, uint32_t u32PreferredProtocols));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderDownDisconnect,(PPDMICARDREADERDOWN pInterface, void *pvUser,
+ uint32_t u32Disposition));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderDownStatus,(PPDMICARDREADERDOWN pInterface, void *pvUser,
+ uint32_t cchReaderName, uint32_t cbAtrLen));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderDownReleaseContext,(PPDMICARDREADERDOWN pInterface, void *pvUser));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderDownGetStatusChange,(PPDMICARDREADERDOWN pInterface, void *pvUser,
+ uint32_t u32Timeout, PDMICARDREADER_READERSTATE *paReaderStats, uint32_t cReaderStats));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderDownBeginTransaction,(PPDMICARDREADERDOWN pInterface, void *pvUser));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderDownEndTransaction,(PPDMICARDREADERDOWN pInterface, void *pvUser,
+ uint32_t u32Disposition));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderDownTransmit,(PPDMICARDREADERDOWN pInterface, void *pvUser,
+ const PDMICARDREADER_IO_REQUEST *pioSendRequest,
+ const uint8_t *pu8SendBuffer, uint32_t cbSendBuffer, uint32_t cbRecvBuffer));
+ /**
+ * Up level provides pvInBuffer of cbInBuffer bytes to call SCardControl, also it specify bytes it expects to receive
+ * @note: device/driver implementation should copy buffers before execution in async mode, and both layers shouldn't
+ * expect permanent storage for the buffer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderDownControl,(PPDMICARDREADERDOWN pInterface, void *pvUser,
+ uint32_t u32ControlCode, const void *pvInBuffer, uint32_t cbInBuffer, uint32_t cbOutBuffer));
+ /**
+ * This function ask driver to provide attribute (dwAttribId) and provide limit (cbAttrib) of buffer size for attribute value,
+ * Callback UpGetAttrib returns buffer containing the value and altered size of the buffer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderDownGetAttr,(PPDMICARDREADERDOWN pInterface, void *pvUser,
+ uint32_t u32AttribId, uint32_t cbAttrib));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderDownSetAttr,(PPDMICARDREADERDOWN pInterface, void *pvUser,
+ uint32_t u32AttribId, const void *pvAttrib, uint32_t cbAttrib));
+};
+
+#define PDMICARDREADERUP_IID "c0d7498e-0635-48ca-aab1-b11b6a55cf7d"
+typedef struct PDMICARDREADERUP PDMICARDREADERUP;
+typedef PDMICARDREADERUP *PPDMICARDREADERUP;
+struct PDMICARDREADERUP
+{
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderUpEstablishContext,(PPDMICARDREADERUP pInterface, int32_t lSCardRc));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderUpStatus,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc,
+ char *pszReaderName, uint32_t cchReaderName, uint32_t u32CardState,
+ uint32_t u32Protocol, uint8_t *pu8Atr, uint32_t cbAtr));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderUpConnect,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc,
+ uint32_t u32ActiveProtocol));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderUpDisconnect,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderUpSetStatusChange,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc,
+ PDMICARDREADER_READERSTATE *paReaderStats, uint32_t cReaderStats));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderUpBeginTransaction,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderUpEndTransaction,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc));
+ /* Note: pioRecvPci stack variable */
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderUpTransmit,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc,
+ const PDMICARDREADER_IO_REQUEST *pioRecvPci, uint8_t *pu8RecvBuffer, uint32_t cbRecvBuffer));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderUpControl,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc,
+ uint32_t u32ControlCode, void *pvOutBuffer, uint32_t cbOutBuffer));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderUpGetAttrib,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc,
+ uint32_t u32AttribId, void *pvAttrib, uint32_t cbAttrib));
+ DECLR3CALLBACKMEMBER(int, pfnCardReaderUpSetAttrib,(PPDMICARDREADERUP pInterface, void *pvUser, int32_t lSCardRc,
+ uint32_t u32AttribId));
+};
+
+#endif
diff --git a/include/VBox/vmm/pdmcommon.h b/include/VBox/vmm/pdmcommon.h
new file mode 100644
index 00000000..c4e1be26
--- /dev/null
+++ b/include/VBox/vmm/pdmcommon.h
@@ -0,0 +1,164 @@
+/** @file
+ * PDM - Pluggable Device Manager, Common Definitions & Types.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmcommon_h
+#define ___VBox_vmm_pdmcommon_h
+
+#include <VBox/types.h>
+
+
+/** @defgroup grp_pdm_common Common Definitions & Types
+ * @ingroup grp_pdm
+ *
+ * Not all the types here are "common", they are here to work around header
+ * ordering issues.
+ *
+ * @{
+ */
+
+/** Makes a PDM structure version out of an unique magic value and major &
+ * minor version numbers.
+ *
+ * @returns 32-bit structure version number.
+ *
+ * @param uMagic 16-bit magic value. This must be unique.
+ * @param uMajor 12-bit major version number. Structures with different
+ * major numbers are not compatible.
+ * @param uMinor 4-bit minor version number. When only the minor version
+ * differs, the structures will be 100% backwards
+ * compatible.
+ */
+#define PDM_VERSION_MAKE(uMagic, uMajor, uMinor) \
+ ( ((uint32_t)(uMagic) << 16) | ((uint32_t)((uMajor) & 0xff) << 4) | ((uint32_t)((uMinor) & 0xf) << 0) )
+
+/** Checks if @a uVerMagic1 is compatible with @a uVerMagic2.
+ *
+ * @returns true / false.
+ * @param uVerMagic1 Typically the runtime version of the struct. This must
+ * have the same magic and major version as @a uVerMagic2
+ * and the minor version must be greater or equal to that
+ * of @a uVerMagic2.
+ * @param uVerMagic2 Typically the version the code was compiled against.
+ *
+ * @remarks The parameters will be referenced more than once.
+ */
+#define PDM_VERSION_ARE_COMPATIBLE(uVerMagic1, uVerMagic2) \
+ ( (uVerMagic1) == (uVerMagic2) \
+ || ( (uVerMagic1) >= (uVerMagic2) \
+ && ((uVerMagic1) & UINT32_C(0xfffffff0)) == ((uVerMagic2) & UINT32_C(0xfffffff0)) ) \
+ )
+
+
+/** PDM Attach/Detach Callback Flags.
+ * Used by PDMDeviceAttach, PDMDeviceDetach, PDMDriverAttach, PDMDriverDetach,
+ * FNPDMDEVATTACH, FNPDMDEVDETACH, FNPDMDRVATTACH, FNPDMDRVDETACH and
+ * FNPDMDRVCONSTRUCT.
+ @{ */
+/** The attach/detach command is not a hotplug event. */
+#define PDM_TACH_FLAGS_NOT_HOT_PLUG RT_BIT_32(0)
+/** Indicates that no attach or detach callbacks should be made.
+ * This is mostly for internal use. */
+#define PDM_TACH_FLAGS_NO_CALLBACKS RT_BIT_32(1)
+/* @} */
+
+
+/**
+ * Is asynchronous handling of suspend or power off notification completed?
+ *
+ * This is called to check whether the USB device has quiesced. Don't deadlock.
+ * Avoid blocking. Do NOT wait for anything.
+ *
+ * @returns true if done, false if more work to be done.
+ *
+ * @param pUsbIns The USB device instance.
+ *
+ * @thread EMT(0)
+ */
+typedef DECLCALLBACK(bool) FNPDMUSBASYNCNOTIFY(PPDMUSBINS pUsbIns);
+/** Pointer to a FNPDMUSBASYNCNOTIFY. */
+typedef FNPDMUSBASYNCNOTIFY *PFNPDMUSBASYNCNOTIFY;
+
+/**
+ * Is asynchronous handling of suspend or power off notification completed?
+ *
+ * This is called to check whether the device has quiesced. Don't deadlock.
+ * Avoid blocking. Do NOT wait for anything.
+ *
+ * @returns true if done, false if more work to be done.
+ *
+ * @param pDevIns The device instance.
+ *
+ * @thread EMT(0)
+ */
+typedef DECLCALLBACK(bool) FNPDMDEVASYNCNOTIFY(PPDMDEVINS pDevIns);
+/** Pointer to a FNPDMDEVASYNCNOTIFY. */
+typedef FNPDMDEVASYNCNOTIFY *PFNPDMDEVASYNCNOTIFY;
+
+/**
+ * Is asynchronous handling of suspend or power off notification completed?
+ *
+ * This is called to check whether the driver has quiesced. Don't deadlock.
+ * Avoid blocking. Do NOT wait for anything.
+ *
+ * @returns true if done, false if more work to be done.
+ *
+ * @param pDrvIns The driver instance.
+ *
+ * @thread EMT(0)
+ */
+typedef DECLCALLBACK(bool) FNPDMDRVASYNCNOTIFY(PPDMDRVINS pDrvIns);
+/** Pointer to a FNPDMDRVASYNCNOTIFY. */
+typedef FNPDMDRVASYNCNOTIFY *PFNPDMDRVASYNCNOTIFY;
+
+
+/**
+ * The ring-0 driver request handler.
+ *
+ * @returns VBox status code. PDMDevHlpCallR0 will return this.
+ * @param pDevIns The device instance (the ring-0 mapping).
+ * @param uOperation The operation.
+ * @param u64Arg Optional integer argument for the operation.
+ */
+typedef DECLCALLBACK(int) FNPDMDEVREQHANDLERR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg);
+/** Ring-0 pointer to a FNPDMDEVREQHANDLERR0. */
+typedef R0PTRTYPE(FNPDMDEVREQHANDLERR0 *) PFNPDMDEVREQHANDLERR0;
+
+/**
+ * The ring-0 driver request handler.
+ *
+ * @returns VBox status code. PDMDrvHlpCallR0 will return this.
+ * @param pDrvIns The driver instance (the ring-0 mapping).
+ * @param uOperation The operation.
+ * @param u64Arg Optional integer argument for the operation.
+ */
+typedef DECLCALLBACK(int) FNPDMDRVREQHANDLERR0(PPDMDRVINS pDrvIns, uint32_t uOperation, uint64_t u64Arg);
+/** Ring-0 pointer to a FNPDMDRVREQHANDLERR0. */
+typedef R0PTRTYPE(FNPDMDRVREQHANDLERR0 *) PFNPDMDRVREQHANDLERR0;
+
+
+/** @} */
+
+#endif
+
diff --git a/include/VBox/vmm/pdmcritsect.h b/include/VBox/vmm/pdmcritsect.h
new file mode 100644
index 00000000..02d7924d
--- /dev/null
+++ b/include/VBox/vmm/pdmcritsect.h
@@ -0,0 +1,95 @@
+/** @file
+ * PDM - Pluggable Device Manager, Critical Sections.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmcritsect_h
+#define ___VBox_vmm_pdmcritsect_h
+
+#include <VBox/types.h>
+#include <iprt/critsect.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_critsect The PDM Critical Section API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/**
+ * A PDM critical section.
+ * Initialize using PDMDRVHLP::pfnCritSectInit().
+ */
+typedef union PDMCRITSECT
+{
+ /** Padding. */
+ uint8_t padding[HC_ARCH_BITS == 32 ? 0x80 : 0xc0];
+#ifdef PDMCRITSECTINT_DECLARED
+ /** The internal structure (not normally visible). */
+ struct PDMCRITSECTINT s;
+#endif
+} PDMCRITSECT;
+
+VMMR3DECL(int) PDMR3CritSectInit(PVM pVM, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL, const char *pszNameFmt, ...);
+VMMDECL(int) PDMCritSectEnter(PPDMCRITSECT pCritSect, int rcBusy);
+VMMDECL(int) PDMCritSectEnterDebug(PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+VMMDECL(int) PDMCritSectTryEnter(PPDMCRITSECT pCritSect);
+VMMDECL(int) PDMCritSectTryEnterDebug(PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL);
+VMMR3DECL(int) PDMR3CritSectEnterEx(PPDMCRITSECT pCritSect, bool fCallRing3);
+VMMDECL(int) PDMCritSectLeave(PPDMCRITSECT pCritSect);
+VMMDECL(bool) PDMCritSectIsOwner(PCPDMCRITSECT pCritSect);
+VMMDECL(bool) PDMCritSectIsOwnerEx(PCPDMCRITSECT pCritSect, PVMCPU pVCpu);
+VMMDECL(bool) PDMCritSectIsInitialized(PCPDMCRITSECT pCritSect);
+VMMDECL(bool) PDMCritSectHasWaiters(PCPDMCRITSECT pCritSect);
+VMMDECL(uint32_t) PDMCritSectGetRecursion(PCPDMCRITSECT pCritSect);
+VMMR3DECL(bool) PDMR3CritSectYield(PPDMCRITSECT pCritSect);
+VMMR3DECL(const char *) PDMR3CritSectName(PCPDMCRITSECT pCritSect);
+VMMR3DECL(int) PDMR3CritSectScheduleExitEvent(PPDMCRITSECT pCritSect, RTSEMEVENT EventToSignal);
+VMMR3DECL(int) PDMR3CritSectDelete(PPDMCRITSECT pCritSect);
+VMMDECL(int) PDMR3CritSectTerm(PVM pVM);
+VMMDECL(void) PDMCritSectFF(PVMCPU pVCpu);
+VMMR3DECL(uint32_t) PDMR3CritSectCountOwned(PVM pVM, char *pszNames, size_t cbNames);
+VMMR3DECL(void) PDMR3CritSectLeaveAll(PVM pVM);
+
+VMMR3DECL(PPDMCRITSECT) PDMR3CritSectGetNop(PVM pVM);
+VMMR3DECL(R0PTRTYPE(PPDMCRITSECT)) PDMR3CritSectGetNopR0(PVM pVM);
+VMMR3DECL(RCPTRTYPE(PPDMCRITSECT)) PDMR3CritSectGetNopRC(PVM pVM);
+
+/* Strict build: Remap the two enter calls to the debug versions. */
+#ifdef VBOX_STRICT
+# ifdef ___iprt_asm_h
+# define PDMCritSectEnter(pCritSect, rcBusy) PDMCritSectEnterDebug((pCritSect), (rcBusy), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# define PDMCritSectTryEnter(pCritSect) PDMCritSectTryEnterDebug((pCritSect), (uintptr_t)ASMReturnAddress(), RT_SRC_POS)
+# else
+# define PDMCritSectEnter(pCritSect, rcBusy) PDMCritSectEnterDebug((pCritSect), (rcBusy), 0, RT_SRC_POS)
+# define PDMCritSectTryEnter(pCritSect) PDMCritSectTryEnterDebug((pCritSect), 0, RT_SRC_POS)
+# endif
+#endif
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/pdmdev.h b/include/VBox/vmm/pdmdev.h
new file mode 100644
index 00000000..892ed590
--- /dev/null
+++ b/include/VBox/vmm/pdmdev.h
@@ -0,0 +1,5173 @@
+/** @file
+ * PDM - Pluggable Device Manager, Devices.
+ */
+
+/*
+ * Copyright (C) 2006-2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmdev_h
+#define ___VBox_vmm_pdmdev_h
+
+#include <VBox/vmm/pdmqueue.h>
+#include <VBox/vmm/pdmcritsect.h>
+#include <VBox/vmm/pdmthread.h>
+#include <VBox/vmm/pdmifs.h>
+#include <VBox/vmm/pdmins.h>
+#include <VBox/vmm/pdmcommon.h>
+#include <VBox/vmm/iom.h>
+#include <VBox/vmm/tm.h>
+#include <VBox/vmm/ssm.h>
+#include <VBox/vmm/cfgm.h>
+#include <VBox/vmm/dbgf.h>
+#include <VBox/err.h>
+#include <VBox/pci.h>
+#include <iprt/stdarg.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_device The PDM Devices API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/**
+ * Construct a device instance for a VM.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance data. If the registration structure
+ * is needed, it can be accessed thru pDevIns->pReg.
+ * @param iInstance Instance number. Use this to figure out which registers
+ * and such to use. The instance number is also found in
+ * pDevIns->iInstance, but since it's likely to be
+ * frequently used PDM passes it as parameter.
+ * @param pCfg Configuration node handle for the driver. This is
+ * expected to be in high demand in the constructor and is
+ * therefore passed as an argument. When using it at other
+ * times, it can be found in pDrvIns->pCfg.
+ */
+typedef DECLCALLBACK(int) FNPDMDEVCONSTRUCT(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg);
+/** Pointer to a FNPDMDEVCONSTRUCT() function. */
+typedef FNPDMDEVCONSTRUCT *PFNPDMDEVCONSTRUCT;
+
+/**
+ * Destruct a device instance.
+ *
+ * Most VM resources are freed by the VM. This callback is provided so that any non-VM
+ * resources can be freed correctly.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance data.
+ *
+ * @remarks The device critical section is not entered. The routine may delete
+ * the critical section, so the caller cannot exit it.
+ */
+typedef DECLCALLBACK(int) FNPDMDEVDESTRUCT(PPDMDEVINS pDevIns);
+/** Pointer to a FNPDMDEVDESTRUCT() function. */
+typedef FNPDMDEVDESTRUCT *PFNPDMDEVDESTRUCT;
+
+/**
+ * Device relocation callback.
+ *
+ * This is called when the instance data has been relocated in raw-mode context
+ * (RC). It is also called when the RC hypervisor selects changes. The device
+ * must fixup all necessary pointers and re-query all interfaces to other RC
+ * devices and drivers.
+ *
+ * Before the RC code is executed the first time, this function will be called
+ * with a 0 delta so RC pointer calculations can be one in one place.
+ *
+ * @param pDevIns Pointer to the device instance.
+ * @param offDelta The relocation delta relative to the old location.
+ *
+ * @remarks A relocation CANNOT fail.
+ *
+ * @remarks The device critical section is not entered. The relocations should
+ * not normally require any locking.
+ */
+typedef DECLCALLBACK(void) FNPDMDEVRELOCATE(PPDMDEVINS pDevIns, RTGCINTPTR offDelta);
+/** Pointer to a FNPDMDEVRELOCATE() function. */
+typedef FNPDMDEVRELOCATE *PFNPDMDEVRELOCATE;
+
+/**
+ * Device I/O Control interface.
+ *
+ * This is used by external components, such as the COM interface, to
+ * communicate with devices using a class wide interface or a device
+ * specific interface.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Pointer to the device instance.
+ * @param uFunction Function to perform.
+ * @param pvIn Pointer to input data.
+ * @param cbIn Size of input data.
+ * @param pvOut Pointer to output data.
+ * @param cbOut Size of output data.
+ * @param pcbOut Where to store the actual size of the output data.
+ *
+ * @remarks Not used.
+ */
+typedef DECLCALLBACK(int) FNPDMDEVIOCTL(PPDMDEVINS pDevIns, uint32_t uFunction,
+ void *pvIn, uint32_t cbIn,
+ void *pvOut, uint32_t cbOut, PRTUINT pcbOut);
+/** Pointer to a FNPDMDEVIOCTL() function. */
+typedef FNPDMDEVIOCTL *PFNPDMDEVIOCTL;
+
+/**
+ * Power On notification.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance data.
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACK(void) FNPDMDEVPOWERON(PPDMDEVINS pDevIns);
+/** Pointer to a FNPDMDEVPOWERON() function. */
+typedef FNPDMDEVPOWERON *PFNPDMDEVPOWERON;
+
+/**
+ * Reset notification.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance data.
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACK(void) FNPDMDEVRESET(PPDMDEVINS pDevIns);
+/** Pointer to a FNPDMDEVRESET() function. */
+typedef FNPDMDEVRESET *PFNPDMDEVRESET;
+
+/**
+ * Suspend notification.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance data.
+ * @thread EMT(0)
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACK(void) FNPDMDEVSUSPEND(PPDMDEVINS pDevIns);
+/** Pointer to a FNPDMDEVSUSPEND() function. */
+typedef FNPDMDEVSUSPEND *PFNPDMDEVSUSPEND;
+
+/**
+ * Resume notification.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance data.
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACK(void) FNPDMDEVRESUME(PPDMDEVINS pDevIns);
+/** Pointer to a FNPDMDEVRESUME() function. */
+typedef FNPDMDEVRESUME *PFNPDMDEVRESUME;
+
+/**
+ * Power Off notification.
+ *
+ * This is only called when the VMR3PowerOff call is made on a running VM. This
+ * means that there is no notification if the VM was suspended before being
+ * powered of. There will also be no callback when hot plugging devices.
+ *
+ * @param pDevIns The device instance data.
+ * @thread EMT(0)
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACK(void) FNPDMDEVPOWEROFF(PPDMDEVINS pDevIns);
+/** Pointer to a FNPDMDEVPOWEROFF() function. */
+typedef FNPDMDEVPOWEROFF *PFNPDMDEVPOWEROFF;
+
+/**
+ * Attach command.
+ *
+ * This is called to let the device attach to a driver for a specified LUN
+ * at runtime. This is not called during VM construction, the device
+ * constructor have to attach to all the available drivers.
+ *
+ * This is like plugging in the keyboard or mouse after turning on the PC.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iLUN The logical unit which is being detached.
+ * @param fFlags Flags, combination of the PDM_TACH_FLAGS_* \#defines.
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACK(int) FNPDMDEVATTACH(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags);
+/** Pointer to a FNPDMDEVATTACH() function. */
+typedef FNPDMDEVATTACH *PFNPDMDEVATTACH;
+
+/**
+ * Detach notification.
+ *
+ * This is called when a driver is detaching itself from a LUN of the device.
+ * The device should adjust it's state to reflect this.
+ *
+ * This is like unplugging the network cable to use it for the laptop or
+ * something while the PC is still running.
+ *
+ * @param pDevIns The device instance.
+ * @param iLUN The logical unit which is being detached.
+ * @param fFlags Flags, combination of the PDMDEVATT_FLAGS_* \#defines.
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACK(void) FNPDMDEVDETACH(PPDMDEVINS pDevIns, unsigned iLUN, uint32_t fFlags);
+/** Pointer to a FNPDMDEVDETACH() function. */
+typedef FNPDMDEVDETACH *PFNPDMDEVDETACH;
+
+/**
+ * Query the base interface of a logical unit.
+ *
+ * @returns VBOX status code.
+ * @param pDevIns The device instance.
+ * @param iLUN The logicial unit to query.
+ * @param ppBase Where to store the pointer to the base interface of the LUN.
+ *
+ * @remarks The device critical section is not entered.
+ */
+typedef DECLCALLBACK(int) FNPDMDEVQUERYINTERFACE(PPDMDEVINS pDevIns, unsigned iLUN, PPDMIBASE *ppBase);
+/** Pointer to a FNPDMDEVQUERYINTERFACE() function. */
+typedef FNPDMDEVQUERYINTERFACE *PFNPDMDEVQUERYINTERFACE;
+
+/**
+ * Init complete notification.
+ * This can be done to do communication with other devices and other
+ * initialization which requires everything to be in place.
+ *
+ * @returns VBOX status code.
+ * @param pDevIns The device instance.
+ *
+ * @remarks Caller enters the device critical section.
+ */
+typedef DECLCALLBACK(int) FNPDMDEVINITCOMPLETE(PPDMDEVINS pDevIns);
+/** Pointer to a FNPDMDEVINITCOMPLETE() function. */
+typedef FNPDMDEVINITCOMPLETE *PFNPDMDEVINITCOMPLETE;
+
+
+
+/**
+ * PDM Device Registration Structure.
+ *
+ * This structure is used when registering a device from VBoxInitDevices() in HC
+ * Ring-3. PDM will continue use till the VM is terminated.
+ */
+typedef struct PDMDEVREG
+{
+ /** Structure version. PDM_DEVREG_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Device name. */
+ char szName[32];
+ /** Name of the raw-mode context module (no path).
+ * Only evalutated if PDM_DEVREG_FLAGS_RC is set. */
+ char szRCMod[32];
+ /** Name of the ring-0 module (no path).
+ * Only evalutated if PDM_DEVREG_FLAGS_R0 is set. */
+ char szR0Mod[32];
+ /** The description of the device. The UTF-8 string pointed to shall, like this structure,
+ * remain unchanged from registration till VM destruction. */
+ const char *pszDescription;
+
+ /** Flags, combination of the PDM_DEVREG_FLAGS_* \#defines. */
+ uint32_t fFlags;
+ /** Device class(es), combination of the PDM_DEVREG_CLASS_* \#defines. */
+ uint32_t fClass;
+ /** Maximum number of instances (per VM). */
+ uint32_t cMaxInstances;
+ /** Size of the instance data. */
+ uint32_t cbInstance;
+
+ /** Construct instance - required. */
+ PFNPDMDEVCONSTRUCT pfnConstruct;
+ /** Destruct instance - optional.
+ * Critical section NOT entered (will be destroyed). */
+ PFNPDMDEVDESTRUCT pfnDestruct;
+ /** Relocation command - optional.
+ * Critical section NOT entered. */
+ PFNPDMDEVRELOCATE pfnRelocate;
+ /** I/O Control interface - optional.
+ * Not used. */
+ PFNPDMDEVIOCTL pfnIOCtl;
+ /** Power on notification - optional.
+ * Critical section is entered. */
+ PFNPDMDEVPOWERON pfnPowerOn;
+ /** Reset notification - optional.
+ * Critical section is entered. */
+ PFNPDMDEVRESET pfnReset;
+ /** Suspend notification - optional.
+ * Critical section is entered. */
+ PFNPDMDEVSUSPEND pfnSuspend;
+ /** Resume notification - optional.
+ * Critical section is entered. */
+ PFNPDMDEVRESUME pfnResume;
+ /** Attach command - optional.
+ * Critical section is entered. */
+ PFNPDMDEVATTACH pfnAttach;
+ /** Detach notification - optional.
+ * Critical section is entered. */
+ PFNPDMDEVDETACH pfnDetach;
+ /** Query a LUN base interface - optional.
+ * Critical section is NOT entered. */
+ PFNPDMDEVQUERYINTERFACE pfnQueryInterface;
+ /** Init complete notification - optional.
+ * Critical section is entered. */
+ PFNPDMDEVINITCOMPLETE pfnInitComplete;
+ /** Power off notification - optional.
+ * Critical section is entered. */
+ PFNPDMDEVPOWEROFF pfnPowerOff;
+ /** @todo */
+ PFNRT pfnSoftReset;
+ /** Initialization safty marker. */
+ uint32_t u32VersionEnd;
+} PDMDEVREG;
+/** Pointer to a PDM Device Structure. */
+typedef PDMDEVREG *PPDMDEVREG;
+/** Const pointer to a PDM Device Structure. */
+typedef PDMDEVREG const *PCPDMDEVREG;
+
+/** Current DEVREG version number. */
+#define PDM_DEVREG_VERSION PDM_VERSION_MAKE(0xffff, 1, 0)
+
+/** PDM Device Flags.
+ * @{ */
+/** This flag is used to indicate that the device has a RC component. */
+#define PDM_DEVREG_FLAGS_RC 0x00000001
+/** This flag is used to indicate that the device has a R0 component. */
+#define PDM_DEVREG_FLAGS_R0 0x00000002
+
+/** @def PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT
+ * The bit count for the current host. */
+#if HC_ARCH_BITS == 32
+# define PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT 0x00000010
+#elif HC_ARCH_BITS == 64
+# define PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT 0x00000020
+#else
+# error Unsupported HC_ARCH_BITS value.
+#endif
+/** The host bit count mask. */
+#define PDM_DEVREG_FLAGS_HOST_BITS_MASK 0x00000030
+
+/** The device support only 32-bit guests. */
+#define PDM_DEVREG_FLAGS_GUEST_BITS_32 0x00000100
+/** The device support only 64-bit guests. */
+#define PDM_DEVREG_FLAGS_GUEST_BITS_64 0x00000200
+/** The device support both 32-bit & 64-bit guests. */
+#define PDM_DEVREG_FLAGS_GUEST_BITS_32_64 0x00000300
+/** @def PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT
+ * The guest bit count for the current compilation. */
+#if GC_ARCH_BITS == 32
+# define PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT PDM_DEVREG_FLAGS_GUEST_BITS_32
+#elif GC_ARCH_BITS == 64
+# define PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT PDM_DEVREG_FLAGS_GUEST_BITS_32_64
+#else
+# error Unsupported GC_ARCH_BITS value.
+#endif
+/** The guest bit count mask. */
+#define PDM_DEVREG_FLAGS_GUEST_BITS_MASK 0x00000300
+
+/** A convenience. */
+#define PDM_DEVREG_FLAGS_DEFAULT_BITS (PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT | PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT)
+
+/** Indicates that the devices support PAE36 on a 32-bit guest. */
+#define PDM_DEVREG_FLAGS_PAE36 0x00001000
+
+/** Indicates that the device needs to be notified before the drivers when suspending. */
+#define PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION 0x00002000
+
+/** Indicates that the device needs to be notified before the drivers when powering off. */
+#define PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION 0x00004000
+
+/** Indicates that the device needs to be notified before the drivers when resetting. */
+#define PDM_DEVREG_FLAGS_FIRST_RESET_NOTIFICATION 0x00008000
+/** @} */
+
+
+/** PDM Device Classes.
+ * The order is important, lower bit earlier instantiation.
+ * @{ */
+/** Architecture device. */
+#define PDM_DEVREG_CLASS_ARCH RT_BIT(0)
+/** Architecture BIOS device. */
+#define PDM_DEVREG_CLASS_ARCH_BIOS RT_BIT(1)
+/** PCI bus brigde. */
+#define PDM_DEVREG_CLASS_BUS_PCI RT_BIT(2)
+/** ISA bus brigde. */
+#define PDM_DEVREG_CLASS_BUS_ISA RT_BIT(3)
+/** Input device (mouse, keyboard, joystick, HID, ...). */
+#define PDM_DEVREG_CLASS_INPUT RT_BIT(4)
+/** Interrupt controller (PIC). */
+#define PDM_DEVREG_CLASS_PIC RT_BIT(5)
+/** Interval controoler (PIT). */
+#define PDM_DEVREG_CLASS_PIT RT_BIT(6)
+/** RTC/CMOS. */
+#define PDM_DEVREG_CLASS_RTC RT_BIT(7)
+/** DMA controller. */
+#define PDM_DEVREG_CLASS_DMA RT_BIT(8)
+/** VMM Device. */
+#define PDM_DEVREG_CLASS_VMM_DEV RT_BIT(9)
+/** Graphics device, like VGA. */
+#define PDM_DEVREG_CLASS_GRAPHICS RT_BIT(10)
+/** Storage controller device. */
+#define PDM_DEVREG_CLASS_STORAGE RT_BIT(11)
+/** Network interface controller. */
+#define PDM_DEVREG_CLASS_NETWORK RT_BIT(12)
+/** Audio. */
+#define PDM_DEVREG_CLASS_AUDIO RT_BIT(13)
+/** USB HIC. */
+#define PDM_DEVREG_CLASS_BUS_USB RT_BIT(14)
+/** ACPI. */
+#define PDM_DEVREG_CLASS_ACPI RT_BIT(15)
+/** Serial controller device. */
+#define PDM_DEVREG_CLASS_SERIAL RT_BIT(16)
+/** Parallel controller device */
+#define PDM_DEVREG_CLASS_PARALLEL RT_BIT(17)
+/** Host PCI pass-through device */
+#define PDM_DEVREG_CLASS_HOST_DEV RT_BIT(18)
+/** Misc devices (always last). */
+#define PDM_DEVREG_CLASS_MISC RT_BIT(31)
+/** @} */
+
+
+/** @name IRQ Level for use with the *SetIrq APIs.
+ * @{
+ */
+/** Assert the IRQ (can assume value 1). */
+#define PDM_IRQ_LEVEL_HIGH RT_BIT(0)
+/** Deassert the IRQ (can assume value 0). */
+#define PDM_IRQ_LEVEL_LOW 0
+/** flip-flop - deassert and then assert the IRQ again immediately. */
+#define PDM_IRQ_LEVEL_FLIP_FLOP (RT_BIT(1) | PDM_IRQ_LEVEL_HIGH)
+/** @} */
+
+/**
+ * Registration record for MSI.
+ */
+typedef struct PDMMSIREG
+{
+ /** Number of MSI interrupt vectors, 0 if MSI not supported */
+ uint16_t cMsiVectors;
+ /** Offset of MSI capability */
+ uint8_t iMsiCapOffset;
+ /** Offset of next capability to MSI */
+ uint8_t iMsiNextOffset;
+ /** If we support 64-bit MSI addressing */
+ bool fMsi64bit;
+
+ /** Number of MSI-X interrupt vectors, 0 if MSI-X not supported */
+ uint16_t cMsixVectors;
+ /** Offset of MSI-X capability */
+ uint8_t iMsixCapOffset;
+ /** Offset of next capability to MSI-X */
+ uint8_t iMsixNextOffset;
+ /** Value of PCI BAR (base addresss register) assigned by device for MSI-X page access */
+ uint8_t iMsixBar;
+} PDMMSIREG;
+typedef PDMMSIREG *PPDMMSIREG;
+
+/**
+ * PCI Bus registration structure.
+ * All the callbacks, except the PCIBIOS hack, are working on PCI devices.
+ */
+typedef struct PDMPCIBUSREG
+{
+ /** Structure version number. PDM_PCIBUSREG_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Registers the device with the default PCI bus.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev The PCI device structure.
+ * Any PCI enabled device must keep this in it's instance data!
+ * Fill in the PCI data config before registration, please.
+ * @param pszName Pointer to device name (permanent, readonly). For debugging, not unique.
+ * @param iDev The device number ((dev << 3) | function) the device should have on the bus.
+ * If negative, the pci bus device will assign one.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegisterR3,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, const char *pszName, int iDev));
+
+ /**
+ * Initialize MSI support in a PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev The PCI device structure.
+ * @param pMsiReg MSI registration structure
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegisterMsiR3,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PPDMMSIREG pMsiReg));
+
+ /**
+ * Registers a I/O region (memory mapped or I/O ports) for a PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev The PCI device structure.
+ * @param iRegion The region number.
+ * @param cbRegion Size of the region.
+ * @param iType PCI_ADDRESS_SPACE_MEM, PCI_ADDRESS_SPACE_IO or PCI_ADDRESS_SPACE_MEM_PREFETCH.
+ * @param pfnCallback Callback for doing the mapping.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIORegionRegisterR3,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback));
+
+ /**
+ * Register PCI configuration space read/write callbacks.
+ *
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev The PCI device structure.
+ * @param pfnRead Pointer to the user defined PCI config read function.
+ * @param ppfnReadOld Pointer to function pointer which will receive the old (default)
+ * PCI config read function. This way, user can decide when (and if)
+ * to call default PCI config read function. Can be NULL.
+ * @param pfnWrite Pointer to the user defined PCI config write function.
+ * @param pfnWriteOld Pointer to function pointer which will receive the old (default)
+ * PCI config write function. This way, user can decide when (and if)
+ * to call default PCI config write function. Can be NULL.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetConfigCallbacksR3,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
+ PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld));
+
+ /**
+ * Set the IRQ for a PCI device.
+ *
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev The PCI device structure.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetIrqR3,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Saves a state of the PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev Pointer to PCI device.
+ * @param pSSMHandle The handle to save the state to.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSaveExecR3,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSMHandle));
+
+ /**
+ * Loads a saved PCI device state.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the PCI Bus.
+ * @param pPciDev Pointer to PCI device.
+ * @param pSSMHandle The handle to the saved state.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLoadExecR3,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PSSMHANDLE pSSMHandle));
+
+ /**
+ * Called to perform the job of the bios.
+ * This is only called for the first PCI Bus - it is expected to
+ * service all the PCI buses.
+ *
+ * @returns VBox status.
+ * @param pDevIns Device instance of the first bus.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFakePCIBIOSR3,(PPDMDEVINS pDevIns));
+
+ /** The name of the SetIrq RC entry point. */
+ const char *pszSetIrqRC;
+
+ /** The name of the SetIrq R0 entry point. */
+ const char *pszSetIrqR0;
+
+} PDMPCIBUSREG;
+/** Pointer to a PCI bus registration structure. */
+typedef PDMPCIBUSREG *PPDMPCIBUSREG;
+
+/** Current PDMPCIBUSREG version number. */
+#define PDM_PCIBUSREG_VERSION PDM_VERSION_MAKE(0xfffe, 3, 0)
+
+/**
+ * PCI Bus RC helpers.
+ */
+typedef struct PDMPCIHLPRC
+{
+ /** Structure version. PDM_PCIHLPRC_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set an ISA IRQ.
+ *
+ * @param pDevIns PCI device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @thread EMT only.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnIsaSetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Set an I/O-APIC IRQ.
+ *
+ * @param pDevIns PCI device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @thread EMT only.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnIoApicSetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Send an MSI.
+ *
+ * @param pDevIns PCI device instance.
+ * @param GCPhys Physical address MSI request was written.
+ * @param uValue Value written.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @thread EMT only.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnIoApicSendMsi,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc));
+
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to acquire the lock.
+ * @param pDevIns The PCI device instance.
+ * @param rc What to return if we fail to acquire the lock.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The PCI device instance.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPCIHLPRC;
+/** Pointer to PCI helpers. */
+typedef RCPTRTYPE(PDMPCIHLPRC *) PPDMPCIHLPRC;
+/** Pointer to const PCI helpers. */
+typedef RCPTRTYPE(const PDMPCIHLPRC *) PCPDMPCIHLPRC;
+
+/** Current PDMPCIHLPRC version number. */
+#define PDM_PCIHLPRC_VERSION PDM_VERSION_MAKE(0xfffd, 3, 0)
+
+
+/**
+ * PCI Bus R0 helpers.
+ */
+typedef struct PDMPCIHLPR0
+{
+ /** Structure version. PDM_PCIHLPR0_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set an ISA IRQ.
+ *
+ * @param pDevIns PCI device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @thread EMT only.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnIsaSetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Set an I/O-APIC IRQ.
+ *
+ * @param pDevIns PCI device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @thread EMT only.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnIoApicSetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Send an MSI.
+ *
+ * @param pDevIns PCI device instance.
+ * @param GCPhys Physical address MSI request was written.
+ * @param uValue Value written.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ * @thread EMT only.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnIoApicSendMsi,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc));
+
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to acquire the lock.
+ * @param pDevIns The PCI device instance.
+ * @param rc What to return if we fail to acquire the lock.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The PCI device instance.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPCIHLPR0;
+/** Pointer to PCI helpers. */
+typedef R0PTRTYPE(PDMPCIHLPR0 *) PPDMPCIHLPR0;
+/** Pointer to const PCI helpers. */
+typedef R0PTRTYPE(const PDMPCIHLPR0 *) PCPDMPCIHLPR0;
+
+/** Current PDMPCIHLPR0 version number. */
+#define PDM_PCIHLPR0_VERSION PDM_VERSION_MAKE(0xfffc, 3, 0)
+
+/**
+ * PCI device helpers.
+ */
+typedef struct PDMPCIHLPR3
+{
+ /** Structure version. PDM_PCIHLPR3_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set an ISA IRQ.
+ *
+ * @param pDevIns The PCI device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR3CALLBACKMEMBER(void, pfnIsaSetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Set an I/O-APIC IRQ.
+ *
+ * @param pDevIns The PCI device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR3CALLBACKMEMBER(void, pfnIoApicSetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Send an MSI.
+ *
+ * @param pDevIns PCI device instance.
+ * @param GCPhys Physical address MSI request was written.
+ * @param uValue Value written.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR3CALLBACKMEMBER(void, pfnIoApicSendMsi,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc));
+
+ /**
+ * Checks if the given address is an MMIO2 base address or not.
+ *
+ * @returns true/false accordingly.
+ * @param pDevIns The PCI device instance.
+ * @param pOwner The owner of the memory, optional.
+ * @param GCPhys The address to check.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsMMIO2Base,(PPDMDEVINS pDevIns, PPDMDEVINS pOwner, RTGCPHYS GCPhys));
+
+ /**
+ * Gets the address of the RC PCI Bus helpers.
+ *
+ * This should be called at both construction and relocation time
+ * to obtain the correct address of the RC helpers.
+ *
+ * @returns RC pointer to the PCI Bus helpers.
+ * @param pDevIns Device instance of the PCI Bus.
+ * @thread EMT only.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMPCIHLPRC, pfnGetRCHelpers,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the address of the R0 PCI Bus helpers.
+ *
+ * This should be called at both construction and relocation time
+ * to obtain the correct address of the R0 helpers.
+ *
+ * @returns R0 pointer to the PCI Bus helpers.
+ * @param pDevIns Device instance of the PCI Bus.
+ * @thread EMT only.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMPCIHLPR0, pfnGetR0Helpers,(PPDMDEVINS pDevIns));
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns Fatal error on failure.
+ * @param pDevIns The PCI device instance.
+ * @param rc Dummy for making the interface identical to the RC and R0 versions.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The PCI device instance.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPCIHLPR3;
+/** Pointer to PCI helpers. */
+typedef R3PTRTYPE(PDMPCIHLPR3 *) PPDMPCIHLPR3;
+/** Pointer to const PCI helpers. */
+typedef R3PTRTYPE(const PDMPCIHLPR3 *) PCPDMPCIHLPR3;
+
+/** Current PDMPCIHLPR3 version number. */
+#define PDM_PCIHLPR3_VERSION PDM_VERSION_MAKE(0xfffb, 3, 0)
+
+
+/**
+ * Programmable Interrupt Controller registration structure.
+ */
+typedef struct PDMPICREG
+{
+ /** Structure version number. PDM_PICREG_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set the an IRQ.
+ *
+ * @param pDevIns Device instance of the PIC.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetIrqR3,(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /**
+ * Get a pending interrupt.
+ *
+ * @returns Pending interrupt number.
+ * @param pDevIns Device instance of the PIC.
+ * @param puTagSrc Where to return the IRQ tag and source.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetInterruptR3,(PPDMDEVINS pDevIns, uint32_t *puTagSrc));
+
+ /** The name of the RC SetIrq entry point. */
+ const char *pszSetIrqRC;
+ /** The name of the RC GetInterrupt entry point. */
+ const char *pszGetInterruptRC;
+
+ /** The name of the R0 SetIrq entry point. */
+ const char *pszSetIrqR0;
+ /** The name of the R0 GetInterrupt entry point. */
+ const char *pszGetInterruptR0;
+} PDMPICREG;
+/** Pointer to a PIC registration structure. */
+typedef PDMPICREG *PPDMPICREG;
+
+/** Current PDMPICREG version number. */
+#define PDM_PICREG_VERSION PDM_VERSION_MAKE(0xfffa, 2, 0)
+
+/**
+ * PIC RC helpers.
+ */
+typedef struct PDMPICHLPRC
+{
+ /** Structure version. PDM_PICHLPRC_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set the interrupt force action flag.
+ *
+ * @param pDevIns Device instance of the PIC.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnSetInterruptFF,(PPDMDEVINS pDevIns));
+
+ /**
+ * Clear the interrupt force action flag.
+ *
+ * @param pDevIns Device instance of the PIC.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnClearInterruptFF,(PPDMDEVINS pDevIns));
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to acquire the lock.
+ * @param pDevIns The PIC device instance.
+ * @param rc What to return if we fail to acquire the lock.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The PIC device instance.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPICHLPRC;
+
+/** Pointer to PIC RC helpers. */
+typedef RCPTRTYPE(PDMPICHLPRC *) PPDMPICHLPRC;
+/** Pointer to const PIC RC helpers. */
+typedef RCPTRTYPE(const PDMPICHLPRC *) PCPDMPICHLPRC;
+
+/** Current PDMPICHLPRC version number. */
+#define PDM_PICHLPRC_VERSION PDM_VERSION_MAKE(0xfff9, 2, 0)
+
+
+/**
+ * PIC R0 helpers.
+ */
+typedef struct PDMPICHLPR0
+{
+ /** Structure version. PDM_PICHLPR0_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set the interrupt force action flag.
+ *
+ * @param pDevIns Device instance of the PIC.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnSetInterruptFF,(PPDMDEVINS pDevIns));
+
+ /**
+ * Clear the interrupt force action flag.
+ *
+ * @param pDevIns Device instance of the PIC.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnClearInterruptFF,(PPDMDEVINS pDevIns));
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to acquire the lock.
+ * @param pDevIns The PIC device instance.
+ * @param rc What to return if we fail to acquire the lock.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The PCI device instance.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPICHLPR0;
+
+/** Pointer to PIC R0 helpers. */
+typedef R0PTRTYPE(PDMPICHLPR0 *) PPDMPICHLPR0;
+/** Pointer to const PIC R0 helpers. */
+typedef R0PTRTYPE(const PDMPICHLPR0 *) PCPDMPICHLPR0;
+
+/** Current PDMPICHLPR0 version number. */
+#define PDM_PICHLPR0_VERSION PDM_VERSION_MAKE(0xfff8, 1, 0)
+
+/**
+ * PIC R3 helpers.
+ */
+typedef struct PDMPICHLPR3
+{
+ /** Structure version. PDM_PICHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set the interrupt force action flag.
+ *
+ * @param pDevIns Device instance of the PIC.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetInterruptFF,(PPDMDEVINS pDevIns));
+
+ /**
+ * Clear the interrupt force action flag.
+ *
+ * @param pDevIns Device instance of the PIC.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnClearInterruptFF,(PPDMDEVINS pDevIns));
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns Fatal error on failure.
+ * @param pDevIns The PIC device instance.
+ * @param rc Dummy for making the interface identical to the RC and R0 versions.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The PIC device instance.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the address of the RC PIC helpers.
+ *
+ * This should be called at both construction and relocation time
+ * to obtain the correct address of the RC helpers.
+ *
+ * @returns RC pointer to the PIC helpers.
+ * @param pDevIns Device instance of the PIC.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMPICHLPRC, pfnGetRCHelpers,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the address of the R0 PIC helpers.
+ *
+ * This should be called at both construction and relocation time
+ * to obtain the correct address of the R0 helpers.
+ *
+ * @returns R0 pointer to the PIC helpers.
+ * @param pDevIns Device instance of the PIC.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMPICHLPR0, pfnGetR0Helpers,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPICHLPR3;
+
+/** Pointer to PIC R3 helpers. */
+typedef R3PTRTYPE(PDMPICHLPR3 *) PPDMPICHLPR3;
+/** Pointer to const PIC R3 helpers. */
+typedef R3PTRTYPE(const PDMPICHLPR3 *) PCPDMPICHLPR3;
+
+/** Current PDMPICHLPR3 version number. */
+#define PDM_PICHLPR3_VERSION PDM_VERSION_MAKE(0xfff7, 1, 0)
+
+
+
+/**
+ * Advanced Programmable Interrupt Controller registration structure.
+ */
+typedef struct PDMAPICREG
+{
+ /** Structure version number. PDM_APICREG_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Get a pending interrupt.
+ *
+ * @returns Pending interrupt number.
+ * @param pDevIns Device instance of the APIC.
+ * @param puTagSrc Where to return the tag source.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetInterruptR3,(PPDMDEVINS pDevIns, uint32_t *puTagSrc));
+
+ /**
+ * Check if the APIC has a pending interrupt/if a TPR change would active one
+ *
+ * @returns Pending interrupt yes/no
+ * @param pDevIns Device instance of the APIC.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnHasPendingIrqR3,(PPDMDEVINS pDevIns));
+
+ /**
+ * Set the APIC base.
+ *
+ * @param pDevIns Device instance of the APIC.
+ * @param u64Base The new base.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetBaseR3,(PPDMDEVINS pDevIns, uint64_t u64Base));
+
+ /**
+ * Get the APIC base.
+ *
+ * @returns Current base.
+ * @param pDevIns Device instance of the APIC.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnGetBaseR3,(PPDMDEVINS pDevIns));
+
+ /**
+ * Set the TPR (task priority register).
+ *
+ * @param pDevIns Device instance of the APIC.
+ * @param idCpu VCPU id
+ * @param u8TPR The new TPR.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetTPRR3,(PPDMDEVINS pDevIns, VMCPUID idCpu, uint8_t u8TPR));
+
+ /**
+ * Get the TPR (task priority register).
+ *
+ * @returns The current TPR.
+ * @param pDevIns Device instance of the APIC.
+ * @param idCpu VCPU id
+ */
+ DECLR3CALLBACKMEMBER(uint8_t, pfnGetTPRR3,(PPDMDEVINS pDevIns, VMCPUID idCpu));
+
+ /**
+ * Write to a MSR in APIC range.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the APIC.
+ * @param idCpu Target CPU.
+ * @param u32Reg The MSR begin written to.
+ * @param u64Value The value to write.
+ *
+ * @remarks Unlike the other callbacks, the PDM lock is not taken before
+ * calling this method.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWriteMSRR3, (PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t u32Reg, uint64_t u64Value));
+
+ /**
+ * Read from a MSR in APIC range.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the APIC.
+ * @param idCpu Target CPU.
+ * @param u32Reg MSR to read.
+ * @param pu64Value Where to return the read value.
+ *
+ * @remarks Unlike the other callbacks, the PDM lock is not taken before
+ * calling this method.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReadMSRR3, (PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t u32Reg, uint64_t *pu64Value));
+
+ /**
+ * Private interface between the IOAPIC and APIC.
+ *
+ * This is a low-level, APIC/IOAPIC implementation specific interface which
+ * is registered with PDM only because it makes life so much simpler right
+ * now (GC bits). This is a bad bad hack! The correct way of doing this
+ * would involve some way of querying GC interfaces and relocating them.
+ * Perhaps doing some kind of device init in GC...
+ *
+ * @returns status code.
+ * @param pDevIns Device instance of the APIC.
+ * @param u8Dest See APIC implementation.
+ * @param u8DestMode See APIC implementation.
+ * @param u8DeliveryMode See APIC implementation.
+ * @param iVector See APIC implementation.
+ * @param u8Polarity See APIC implementation.
+ * @param u8TriggerMode See APIC implementation.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnBusDeliverR3,(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
+ uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc));
+
+ /**
+ * Deliver a signal to CPU's local interrupt pins (LINT0/LINT1).
+ *
+ * Used for virtual wire mode when interrupts from the PIC are passed through
+ * LAPIC.
+ *
+ * @returns status code.
+ * @param pDevIns Device instance of the APIC.
+ * @param u8Pin Local pin number (0 or 1 for current CPUs).
+ * @param u8Level The level.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLocalInterruptR3,(PPDMDEVINS pDevIns, uint8_t u8Pin, uint8_t u8Level));
+
+ /** The name of the RC GetInterrupt entry point. */
+ const char *pszGetInterruptRC;
+ /** The name of the RC HasPendingIrq entry point. */
+ const char *pszHasPendingIrqRC;
+ /** The name of the RC SetBase entry point. */
+ const char *pszSetBaseRC;
+ /** The name of the RC GetBase entry point. */
+ const char *pszGetBaseRC;
+ /** The name of the RC SetTPR entry point. */
+ const char *pszSetTPRRC;
+ /** The name of the RC GetTPR entry point. */
+ const char *pszGetTPRRC;
+ /** The name of the RC WriteMSR entry point. */
+ const char *pszWriteMSRRC;
+ /** The name of the RC ReadMSR entry point. */
+ const char *pszReadMSRRC;
+ /** The name of the RC BusDeliver entry point. */
+ const char *pszBusDeliverRC;
+ /** The name of the RC LocalInterrupt entry point. */
+ const char *pszLocalInterruptRC;
+
+ /** The name of the R0 GetInterrupt entry point. */
+ const char *pszGetInterruptR0;
+ /** The name of the R0 HasPendingIrq entry point. */
+ const char *pszHasPendingIrqR0;
+ /** The name of the R0 SetBase entry point. */
+ const char *pszSetBaseR0;
+ /** The name of the R0 GetBase entry point. */
+ const char *pszGetBaseR0;
+ /** The name of the R0 SetTPR entry point. */
+ const char *pszSetTPRR0;
+ /** The name of the R0 GetTPR entry point. */
+ const char *pszGetTPRR0;
+ /** The name of the R0 WriteMSR entry point. */
+ const char *pszWriteMSRR0;
+ /** The name of the R0 ReadMSR entry point. */
+ const char *pszReadMSRR0;
+ /** The name of the R0 BusDeliver entry point. */
+ const char *pszBusDeliverR0;
+ /** The name of the R0 LocalInterrupt entry point. */
+ const char *pszLocalInterruptR0;
+
+} PDMAPICREG;
+/** Pointer to an APIC registration structure. */
+typedef PDMAPICREG *PPDMAPICREG;
+
+/** Current PDMAPICREG version number. */
+#define PDM_APICREG_VERSION PDM_VERSION_MAKE(0xfff6, 2, 0)
+
+
+/**
+ * APIC version argument for pfnChangeFeature.
+ */
+typedef enum PDMAPICVERSION
+{
+ /** Invalid 0 entry. */
+ PDMAPICVERSION_INVALID = 0,
+ /** No APIC. */
+ PDMAPICVERSION_NONE,
+ /** Standard APIC (X86_CPUID_FEATURE_EDX_APIC). */
+ PDMAPICVERSION_APIC,
+ /** Intel X2APIC (X86_CPUID_FEATURE_ECX_X2APIC). */
+ PDMAPICVERSION_X2APIC,
+ /** The usual 32-bit paranoia. */
+ PDMAPICVERSION_32BIT_HACK = 0x7fffffff
+} PDMAPICVERSION;
+
+/**
+ * APIC irq argument for SetInterruptFF.
+ */
+typedef enum PDMAPICIRQ
+{
+ /** Invalid 0 entry. */
+ PDMAPICIRQ_INVALID = 0,
+ /** Normal hardware interrupt. */
+ PDMAPICIRQ_HARDWARE,
+ /** NMI. */
+ PDMAPICIRQ_NMI,
+ /** SMI. */
+ PDMAPICIRQ_SMI,
+ /** ExtINT (HW interrupt via PIC). */
+ PDMAPICIRQ_EXTINT,
+ /** The usual 32-bit paranoia. */
+ PDMAPICIRQ_32BIT_HACK = 0x7fffffff
+} PDMAPICIRQ;
+
+
+/**
+ * APIC RC helpers.
+ */
+typedef struct PDMAPICHLPRC
+{
+ /** Structure version. PDM_APICHLPRC_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set the interrupt force action flag.
+ *
+ * @param pDevIns Device instance of the APIC.
+ * @param enmType IRQ type.
+ * @param idCpu Virtual CPU to set flag upon.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnSetInterruptFF,(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu));
+
+ /**
+ * Clear the interrupt force action flag.
+ *
+ * @param pDevIns Device instance of the APIC.
+ * @param enmType IRQ type.
+ * @param idCpu Virtual CPU to clear flag upon.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnClearInterruptFF,(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu));
+
+ /**
+ * Calculates an IRQ tag for a timer, IPI or similar event.
+ *
+ * @returns The IRQ tag.
+ * @param pDevIns Device instance of the APIC.
+ * @param u8Level PDM_IRQ_LEVEL_HIGH or PDM_IRQ_LEVEL_FLIP_FLOP.
+ */
+ DECLRCCALLBACKMEMBER(uint32_t, pfnCalcIrqTag,(PPDMDEVINS pDevIns, uint8_t u8Level));
+
+ /**
+ * Modifies APIC-related bits in the CPUID feature mask.
+ *
+ * @param pDevIns Device instance of the APIC.
+ * @param enmVersion Supported APIC version.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnChangeFeature,(PPDMDEVINS pDevIns, PDMAPICVERSION enmVersion));
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to acquire the lock.
+ * @param pDevIns The APIC device instance.
+ * @param rc What to return if we fail to acquire the lock.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The APIC device instance.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the virtual CPU id corresponding to the current EMT.
+ *
+ * @param pDevIns The APIC device instance.
+ */
+ DECLRCCALLBACKMEMBER(VMCPUID, pfnGetCpuId,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMAPICHLPRC;
+/** Pointer to APIC GC helpers. */
+typedef RCPTRTYPE(PDMAPICHLPRC *) PPDMAPICHLPRC;
+/** Pointer to const APIC helpers. */
+typedef RCPTRTYPE(const PDMAPICHLPRC *) PCPDMAPICHLPRC;
+
+/** Current PDMAPICHLPRC version number. */
+#define PDM_APICHLPRC_VERSION PDM_VERSION_MAKE(0xfff5, 2, 0)
+
+
+/**
+ * APIC R0 helpers.
+ */
+typedef struct PDMAPICHLPR0
+{
+ /** Structure version. PDM_APICHLPR0_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set the interrupt force action flag.
+ *
+ * @param pDevIns Device instance of the APIC.
+ * @param enmType IRQ type.
+ * @param idCpu Virtual CPU to set flag upon.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnSetInterruptFF,(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu));
+
+ /**
+ * Clear the interrupt force action flag.
+ *
+ * @param pDevIns Device instance of the APIC.
+ * @param enmType IRQ type.
+ * @param idCpu Virtual CPU to clear flag upon.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnClearInterruptFF,(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu));
+
+ /**
+ * Calculates an IRQ tag for a timer, IPI or similar event.
+ *
+ * @returns The IRQ tag.
+ * @param pDevIns Device instance of the APIC.
+ * @param u8Level PDM_IRQ_LEVEL_HIGH or PDM_IRQ_LEVEL_FLIP_FLOP.
+ */
+ DECLR0CALLBACKMEMBER(uint32_t, pfnCalcIrqTag,(PPDMDEVINS pDevIns, uint8_t u8Level));
+
+ /**
+ * Modifies APIC-related bits in the CPUID feature mask.
+ *
+ * @param pDevIns Device instance of the APIC.
+ * @param enmVersion Supported APIC version.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnChangeFeature,(PPDMDEVINS pDevIns, PDMAPICVERSION enmVersion));
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to acquire the lock.
+ * @param pDevIns The APIC device instance.
+ * @param rc What to return if we fail to acquire the lock.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The APIC device instance.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the virtual CPU id corresponding to the current EMT.
+ *
+ * @param pDevIns The APIC device instance.
+ */
+ DECLR0CALLBACKMEMBER(VMCPUID, pfnGetCpuId,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMAPICHLPR0;
+/** Pointer to APIC GC helpers. */
+typedef RCPTRTYPE(PDMAPICHLPR0 *) PPDMAPICHLPR0;
+/** Pointer to const APIC helpers. */
+typedef R0PTRTYPE(const PDMAPICHLPR0 *) PCPDMAPICHLPR0;
+
+/** Current PDMAPICHLPR0 version number. */
+#define PDM_APICHLPR0_VERSION PDM_VERSION_MAKE(0xfff4, 2, 0)
+
+/**
+ * APIC R3 helpers.
+ */
+typedef struct PDMAPICHLPR3
+{
+ /** Structure version. PDM_APICHLPR3_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set the interrupt force action flag.
+ *
+ * @param pDevIns Device instance of the APIC.
+ * @param enmType IRQ type.
+ * @param idCpu Virtual CPU to set flag upon.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetInterruptFF,(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu));
+
+ /**
+ * Clear the interrupt force action flag.
+ *
+ * @param pDevIns Device instance of the APIC.
+ * @param enmType IRQ type.
+ * @param idCpu Virtual CPU to clear flag upon.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnClearInterruptFF,(PPDMDEVINS pDevIns, PDMAPICIRQ enmType, VMCPUID idCpu));
+
+ /**
+ * Calculates an IRQ tag for a timer, IPI or similar event.
+ *
+ * @returns The IRQ tag.
+ * @param pDevIns Device instance of the APIC.
+ * @param u8Level PDM_IRQ_LEVEL_HIGH or PDM_IRQ_LEVEL_FLIP_FLOP.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnCalcIrqTag,(PPDMDEVINS pDevIns, uint8_t u8Level));
+
+ /**
+ * Modifies APIC-related bits in the CPUID feature mask.
+ *
+ * @param pDevIns Device instance of the APIC.
+ * @param enmVersion Supported APIC version.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnChangeFeature,(PPDMDEVINS pDevIns, PDMAPICVERSION enmVersion));
+
+ /**
+ * Get the virtual CPU id corresponding to the current EMT.
+ *
+ * @param pDevIns The APIC device instance.
+ */
+ DECLR3CALLBACKMEMBER(VMCPUID, pfnGetCpuId,(PPDMDEVINS pDevIns));
+
+ /**
+ * Sends SIPI to given virtual CPU.
+ *
+ * @param pDevIns The APIC device instance.
+ * @param idCpu Virtual CPU to perform SIPI on
+ * @param iVector SIPI vector
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSendSipi,(PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t uVector));
+
+ /**
+ * Sends init IPI to given virtual CPU, should result in reset and
+ * halting till SIPI.
+ *
+ * @param pDevIns The APIC device instance.
+ * @param idCpu Virtual CPU to perform SIPI on
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSendInitIpi,(PPDMDEVINS pDevIns, VMCPUID idCpu));
+
+ /**
+ * Gets the address of the RC APIC helpers.
+ *
+ * This should be called at both construction and relocation time
+ * to obtain the correct address of the RC helpers.
+ *
+ * @returns GC pointer to the APIC helpers.
+ * @param pDevIns Device instance of the APIC.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMAPICHLPRC, pfnGetRCHelpers,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the address of the R0 APIC helpers.
+ *
+ * This should be called at both construction and relocation time
+ * to obtain the correct address of the R0 helpers.
+ *
+ * @returns R0 pointer to the APIC helpers.
+ * @param pDevIns Device instance of the APIC.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMAPICHLPR0, pfnGetR0Helpers,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the critical section used to synchronize the PICs, PCI and stuff.
+ *
+ * @returns Ring-3 pointer to the critical section.
+ * @param pDevIns The APIC device instance.
+ */
+ DECLR3CALLBACKMEMBER(R3PTRTYPE(PPDMCRITSECT), pfnGetR3CritSect,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the critical section used to synchronize the PICs, PCI and stuff.
+ *
+ * @returns Raw-mode context pointer to the critical section.
+ * @param pDevIns The APIC device instance.
+ */
+ DECLR3CALLBACKMEMBER(RCPTRTYPE(PPDMCRITSECT), pfnGetRCCritSect,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the critical section used to synchronize the PICs, PCI and stuff.
+ *
+ * @returns Ring-0 pointer to the critical section.
+ * @param pDevIns The APIC device instance.
+ */
+ DECLR3CALLBACKMEMBER(R0PTRTYPE(PPDMCRITSECT), pfnGetR0CritSect,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMAPICHLPR3;
+/** Pointer to APIC helpers. */
+typedef R3PTRTYPE(PDMAPICHLPR3 *) PPDMAPICHLPR3;
+/** Pointer to const APIC helpers. */
+typedef R3PTRTYPE(const PDMAPICHLPR3 *) PCPDMAPICHLPR3;
+
+/** Current PDMAPICHLP version number. */
+#define PDM_APICHLPR3_VERSION PDM_VERSION_MAKE(0xfff3, 2, 0)
+
+
+/**
+ * I/O APIC registration structure.
+ */
+typedef struct PDMIOAPICREG
+{
+ /** Struct version+magic number (PDM_IOAPICREG_VERSION). */
+ uint32_t u32Version;
+
+ /**
+ * Set the an IRQ.
+ *
+ * @param pDevIns Device instance of the I/O APIC.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetIrqR3,(PPDMDEVINS pDevIns, int iIrq, int iLevel, uint32_t uTagSrc));
+
+ /** The name of the RC SetIrq entry point. */
+ const char *pszSetIrqRC;
+
+ /** The name of the R0 SetIrq entry point. */
+ const char *pszSetIrqR0;
+
+ /**
+ * Send a MSI.
+ *
+ * @param pDevIns Device instance of the I/O APIC.
+ * @param GCPhys Request address.
+ * @param uValue Request value.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSendMsiR3,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t uValue, uint32_t uTagSrc));
+
+ /** The name of the RC SendMsi entry point. */
+ const char *pszSendMsiRC;
+
+ /** The name of the R0 SendMsi entry point. */
+ const char *pszSendMsiR0;
+} PDMIOAPICREG;
+/** Pointer to an APIC registration structure. */
+typedef PDMIOAPICREG *PPDMIOAPICREG;
+
+/** Current PDMAPICREG version number. */
+#define PDM_IOAPICREG_VERSION PDM_VERSION_MAKE(0xfff2, 3, 0)
+
+
+/**
+ * IOAPIC RC helpers.
+ */
+typedef struct PDMIOAPICHLPRC
+{
+ /** Structure version. PDM_IOAPICHLPRC_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Private interface between the IOAPIC and APIC.
+ *
+ * See comments about this hack on PDMAPICREG::pfnBusDeliverR3.
+ *
+ * @returns status code.
+ * @param pDevIns Device instance of the IOAPIC.
+ * @param u8Dest See APIC implementation.
+ * @param u8DestMode See APIC implementation.
+ * @param u8DeliveryMode See APIC implementation.
+ * @param iVector See APIC implementation.
+ * @param u8Polarity See APIC implementation.
+ * @param u8TriggerMode See APIC implementation.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLRCCALLBACKMEMBER(int, pfnApicBusDeliver,(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
+ uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc));
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to acquire the lock.
+ * @param pDevIns The IOAPIC device instance.
+ * @param rc What to return if we fail to acquire the lock.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The IOAPIC device instance.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMIOAPICHLPRC;
+/** Pointer to IOAPIC RC helpers. */
+typedef RCPTRTYPE(PDMIOAPICHLPRC *) PPDMIOAPICHLPRC;
+/** Pointer to const IOAPIC helpers. */
+typedef RCPTRTYPE(const PDMIOAPICHLPRC *) PCPDMIOAPICHLPRC;
+
+/** Current PDMIOAPICHLPRC version number. */
+#define PDM_IOAPICHLPRC_VERSION PDM_VERSION_MAKE(0xfff1, 2, 0)
+
+
+/**
+ * IOAPIC R0 helpers.
+ */
+typedef struct PDMIOAPICHLPR0
+{
+ /** Structure version. PDM_IOAPICHLPR0_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Private interface between the IOAPIC and APIC.
+ *
+ * See comments about this hack on PDMAPICREG::pfnBusDeliverR3.
+ *
+ * @returns status code.
+ * @param pDevIns Device instance of the IOAPIC.
+ * @param u8Dest See APIC implementation.
+ * @param u8DestMode See APIC implementation.
+ * @param u8DeliveryMode See APIC implementation.
+ * @param iVector See APIC implementation.
+ * @param u8Polarity See APIC implementation.
+ * @param u8TriggerMode See APIC implementation.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR0CALLBACKMEMBER(int, pfnApicBusDeliver,(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
+ uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc));
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to acquire the lock.
+ * @param pDevIns The IOAPIC device instance.
+ * @param rc What to return if we fail to acquire the lock.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The IOAPIC device instance.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMIOAPICHLPR0;
+/** Pointer to IOAPIC R0 helpers. */
+typedef R0PTRTYPE(PDMIOAPICHLPR0 *) PPDMIOAPICHLPR0;
+/** Pointer to const IOAPIC helpers. */
+typedef R0PTRTYPE(const PDMIOAPICHLPR0 *) PCPDMIOAPICHLPR0;
+
+/** Current PDMIOAPICHLPR0 version number. */
+#define PDM_IOAPICHLPR0_VERSION PDM_VERSION_MAKE(0xfff0, 2, 0)
+
+/**
+ * IOAPIC R3 helpers.
+ */
+typedef struct PDMIOAPICHLPR3
+{
+ /** Structure version. PDM_IOAPICHLPR3_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Private interface between the IOAPIC and APIC.
+ *
+ * See comments about this hack on PDMAPICREG::pfnBusDeliverR3.
+ *
+ * @returns status code
+ * @param pDevIns Device instance of the IOAPIC.
+ * @param u8Dest See APIC implementation.
+ * @param u8DestMode See APIC implementation.
+ * @param u8DeliveryMode See APIC implementation.
+ * @param iVector See APIC implementation.
+ * @param u8Polarity See APIC implementation.
+ * @param u8TriggerMode See APIC implementation.
+ * @param uTagSrc The IRQ tag and source (for tracing).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnApicBusDeliver,(PPDMDEVINS pDevIns, uint8_t u8Dest, uint8_t u8DestMode, uint8_t u8DeliveryMode,
+ uint8_t iVector, uint8_t u8Polarity, uint8_t u8TriggerMode, uint32_t uTagSrc));
+
+ /**
+ * Acquires the PDM lock.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns Fatal error on failure.
+ * @param pDevIns The IOAPIC device instance.
+ * @param rc Dummy for making the interface identical to the GC and R0 versions.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLock,(PPDMDEVINS pDevIns, int rc));
+
+ /**
+ * Releases the PDM lock.
+ *
+ * @param pDevIns The IOAPIC device instance.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUnlock,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the address of the RC IOAPIC helpers.
+ *
+ * This should be called at both construction and relocation time
+ * to obtain the correct address of the RC helpers.
+ *
+ * @returns RC pointer to the IOAPIC helpers.
+ * @param pDevIns Device instance of the IOAPIC.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMIOAPICHLPRC, pfnGetRCHelpers,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the address of the R0 IOAPIC helpers.
+ *
+ * This should be called at both construction and relocation time
+ * to obtain the correct address of the R0 helpers.
+ *
+ * @returns R0 pointer to the IOAPIC helpers.
+ * @param pDevIns Device instance of the IOAPIC.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMIOAPICHLPR0, pfnGetR0Helpers,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMIOAPICHLPR3;
+/** Pointer to IOAPIC R3 helpers. */
+typedef R3PTRTYPE(PDMIOAPICHLPR3 *) PPDMIOAPICHLPR3;
+/** Pointer to const IOAPIC helpers. */
+typedef R3PTRTYPE(const PDMIOAPICHLPR3 *) PCPDMIOAPICHLPR3;
+
+/** Current PDMIOAPICHLPR3 version number. */
+#define PDM_IOAPICHLPR3_VERSION PDM_VERSION_MAKE(0xffef, 2, 0)
+
+
+/**
+ * HPET registration structure.
+ */
+typedef struct PDMHPETREG
+{
+ /** Struct version+magic number (PDM_HPETREG_VERSION). */
+ uint32_t u32Version;
+
+} PDMHPETREG;
+/** Pointer to an HPET registration structure. */
+typedef PDMHPETREG *PPDMHPETREG;
+
+/** Current PDMHPETREG version number. */
+#define PDM_HPETREG_VERSION PDM_VERSION_MAKE(0xffe2, 1, 0)
+
+/**
+ * HPET RC helpers.
+ *
+ * @remarks Keep this around in case HPET will need PDM interaction in again RC
+ * at some later point.
+ */
+typedef struct PDMHPETHLPRC
+{
+ /** Structure version. PDM_HPETHLPRC_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMHPETHLPRC;
+
+/** Pointer to HPET RC helpers. */
+typedef RCPTRTYPE(PDMHPETHLPRC *) PPDMHPETHLPRC;
+/** Pointer to const HPET RC helpers. */
+typedef RCPTRTYPE(const PDMHPETHLPRC *) PCPDMHPETHLPRC;
+
+/** Current PDMHPETHLPRC version number. */
+#define PDM_HPETHLPRC_VERSION PDM_VERSION_MAKE(0xffee, 2, 0)
+
+
+/**
+ * HPET R0 helpers.
+ *
+ * @remarks Keep this around in case HPET will need PDM interaction in again R0
+ * at some later point.
+ */
+typedef struct PDMHPETHLPR0
+{
+ /** Structure version. PDM_HPETHLPR0_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMHPETHLPR0;
+
+/** Pointer to HPET R0 helpers. */
+typedef R0PTRTYPE(PDMHPETHLPR0 *) PPDMHPETHLPR0;
+/** Pointer to const HPET R0 helpers. */
+typedef R0PTRTYPE(const PDMHPETHLPR0 *) PCPDMHPETHLPR0;
+
+/** Current PDMHPETHLPR0 version number. */
+#define PDM_HPETHLPR0_VERSION PDM_VERSION_MAKE(0xffed, 2, 0)
+
+/**
+ * HPET R3 helpers.
+ */
+typedef struct PDMHPETHLPR3
+{
+ /** Structure version. PDM_HPETHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Gets the address of the RC HPET helpers.
+ *
+ * This should be called at both construction and relocation time
+ * to obtain the correct address of the RC helpers.
+ *
+ * @returns RC pointer to the HPET helpers.
+ * @param pDevIns Device instance of the HPET.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMHPETHLPRC, pfnGetRCHelpers,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the address of the R0 HPET helpers.
+ *
+ * This should be called at both construction and relocation time
+ * to obtain the correct address of the R0 helpers.
+ *
+ * @returns R0 pointer to the HPET helpers.
+ * @param pDevIns Device instance of the HPET.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMHPETHLPR0, pfnGetR0Helpers,(PPDMDEVINS pDevIns));
+
+ /**
+ * Set legacy mode on PIT and RTC.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to set legacy mode.
+ * @param pDevIns Device instance of the HPET.
+ * @param fActivated Whether legacy mode is activated or deactivated.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetLegacyMode,(PPDMDEVINS pDevIns, bool fActivated));
+
+
+ /**
+ * Set IRQ, bypassing ISA bus override rules.
+ *
+ * @returns VINF_SUCCESS on success.
+ * @returns rc if we failed to set legacy mode.
+ * @param pDevIns Device instance of the HPET.
+ * @param fActivate Activate or deactivate legacy mode.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMHPETHLPR3;
+
+/** Pointer to HPET R3 helpers. */
+typedef R3PTRTYPE(PDMHPETHLPR3 *) PPDMHPETHLPR3;
+/** Pointer to const HPET R3 helpers. */
+typedef R3PTRTYPE(const PDMHPETHLPR3 *) PCPDMHPETHLPR3;
+
+/** Current PDMHPETHLPR3 version number. */
+#define PDM_HPETHLPR3_VERSION PDM_VERSION_MAKE(0xffec, 2, 0)
+
+
+/**
+ * Raw PCI device registration structure.
+ */
+typedef struct PDMPCIRAWREG
+{
+ /** Struct version+magic number (PDM_PCIRAWREG_VERSION). */
+ uint32_t u32Version;
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPCIRAWREG;
+/** Pointer to a raw PCI registration structure. */
+typedef PDMPCIRAWREG *PPDMPCIRAWREG;
+
+/** Current PDMPCIRAWREG version number. */
+#define PDM_PCIRAWREG_VERSION PDM_VERSION_MAKE(0xffe1, 1, 0)
+
+/**
+ * Raw PCI device raw-mode context helpers.
+ */
+typedef struct PDMPCIRAWHLPRC
+{
+ /** Structure version and magic number (PDM_PCIRAWHLPRC_VERSION). */
+ uint32_t u32Version;
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPCIRAWHLPRC;
+/** Pointer to a raw PCI deviec raw-mode context helper structure. */
+typedef RCPTRTYPE(PDMPCIRAWHLPRC *) PPDMPCIRAWHLPRC;
+/** Pointer to a const raw PCI deviec raw-mode context helper structure. */
+typedef RCPTRTYPE(const PDMPCIRAWHLPRC *) PCPDMPCIRAWHLPRC;
+
+/** Current PDMPCIRAWHLPRC version number. */
+#define PDM_PCIRAWHLPRC_VERSION PDM_VERSION_MAKE(0xffe0, 1, 0)
+
+/**
+ * Raw PCI device ring-0 context helpers.
+ */
+typedef struct PDMPCIRAWHLPR0
+{
+ /** Structure version and magic number (PDM_PCIRAWHLPR0_VERSION). */
+ uint32_t u32Version;
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPCIRAWHLPR0;
+/** Pointer to a raw PCI deviec ring-0 context helper structure. */
+typedef R0PTRTYPE(PDMPCIRAWHLPR0 *) PPDMPCIRAWHLPR0;
+/** Pointer to a const raw PCI deviec ring-0 context helper structure. */
+typedef R0PTRTYPE(const PDMPCIRAWHLPR0 *) PCPDMPCIRAWHLPR0;
+
+/** Current PDMPCIRAWHLPR0 version number. */
+#define PDM_PCIRAWHLPR0_VERSION PDM_VERSION_MAKE(0xffdf, 1, 0)
+
+
+/**
+ * Raw PCI device ring-3 context helpers.
+ */
+typedef struct PDMPCIRAWHLPR3
+{
+ /** Undefined structure version and magic number. */
+ uint32_t u32Version;
+
+ /**
+ * Gets the address of the RC raw PCI device helpers.
+ *
+ * This should be called at both construction and relocation time to obtain
+ * the correct address of the RC helpers.
+ *
+ * @returns RC pointer to the raw PCI device helpers.
+ * @param pDevIns Device instance of the raw PCI device.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMPCIRAWHLPRC, pfnGetRCHelpers,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the address of the R0 raw PCI device helpers.
+ *
+ * This should be called at both construction and relocation time to obtain
+ * the correct address of the R0 helpers.
+ *
+ * @returns R0 pointer to the raw PCI device helpers.
+ * @param pDevIns Device instance of the raw PCI device.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMPCIRAWHLPR0, pfnGetR0Helpers,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMPCIRAWHLPR3;
+/** Pointer to raw PCI R3 helpers. */
+typedef R3PTRTYPE(PDMPCIRAWHLPR3 *) PPDMPCIRAWHLPR3;
+/** Pointer to const raw PCI R3 helpers. */
+typedef R3PTRTYPE(const PDMPCIRAWHLPR3 *) PCPDMPCIRAWHLPR3;
+
+/** Current PDMPCIRAWHLPR3 version number. */
+#define PDM_PCIRAWHLPR3_VERSION PDM_VERSION_MAKE(0xffde, 1, 0)
+
+
+#ifdef IN_RING3
+
+/**
+ * DMA Transfer Handler.
+ *
+ * @returns Number of bytes transferred.
+ * @param pDevIns Device instance of the DMA.
+ * @param pvUser User pointer.
+ * @param uChannel Channel number.
+ * @param off DMA position.
+ * @param cb Block size.
+ */
+typedef DECLCALLBACK(uint32_t) FNDMATRANSFERHANDLER(PPDMDEVINS pDevIns, void *pvUser, unsigned uChannel, uint32_t off, uint32_t cb);
+/** Pointer to a FNDMATRANSFERHANDLER(). */
+typedef FNDMATRANSFERHANDLER *PFNDMATRANSFERHANDLER;
+
+/**
+ * DMA Controller registration structure.
+ */
+typedef struct PDMDMAREG
+{
+ /** Structure version number. PDM_DMACREG_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Execute pending transfers.
+ *
+ * @returns A more work indiciator. I.e. 'true' if there is more to be done, and 'false' if all is done.
+ * @param pDevIns Device instance of the DMAC.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnRun,(PPDMDEVINS pDevIns));
+
+ /**
+ * Register transfer function for DMA channel.
+ *
+ * @param pDevIns Device instance of the DMAC.
+ * @param uChannel Channel number.
+ * @param pfnTransferHandler Device specific transfer function.
+ * @param pvUSer User pointer to be passed to the callback.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnRegister,(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser));
+
+ /**
+ * Read memory
+ *
+ * @returns Number of bytes read.
+ * @param pDevIns Device instance of the DMAC.
+ * @param pvBuffer Pointer to target buffer.
+ * @param off DMA position.
+ * @param cbBlock Block size.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnReadMemory,(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock));
+
+ /**
+ * Write memory
+ *
+ * @returns Number of bytes written.
+ * @param pDevIns Device instance of the DMAC.
+ * @param pvBuffer Memory to write.
+ * @param off DMA position.
+ * @param cbBlock Block size.
+ */
+ DECLR3CALLBACKMEMBER(uint32_t, pfnWriteMemory,(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock));
+
+ /**
+ * Set the DREQ line.
+ *
+ * @param pDevIns Device instance of the DMAC.
+ * @param uChannel Channel number.
+ * @param uLevel Level of the line.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetDREQ,(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel));
+
+ /**
+ * Get channel mode
+ *
+ * @returns Channel mode.
+ * @param pDevIns Device instance of the DMAC.
+ * @param uChannel Channel number.
+ */
+ DECLR3CALLBACKMEMBER(uint8_t, pfnGetChannelMode,(PPDMDEVINS pDevIns, unsigned uChannel));
+
+} PDMDMACREG;
+/** Pointer to a DMAC registration structure. */
+typedef PDMDMACREG *PPDMDMACREG;
+
+/** Current PDMDMACREG version number. */
+#define PDM_DMACREG_VERSION PDM_VERSION_MAKE(0xffeb, 1, 0)
+
+
+/**
+ * DMA Controller device helpers.
+ */
+typedef struct PDMDMACHLP
+{
+ /** Structure version. PDM_DMACHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /* to-be-defined */
+
+} PDMDMACHLP;
+/** Pointer to DMAC helpers. */
+typedef PDMDMACHLP *PPDMDMACHLP;
+/** Pointer to const DMAC helpers. */
+typedef const PDMDMACHLP *PCPDMDMACHLP;
+
+/** Current PDMDMACHLP version number. */
+#define PDM_DMACHLP_VERSION PDM_VERSION_MAKE(0xffea, 1, 0)
+
+#endif /* IN_RING3 */
+
+
+
+/**
+ * RTC registration structure.
+ */
+typedef struct PDMRTCREG
+{
+ /** Structure version number. PDM_RTCREG_VERSION defines the current version. */
+ uint32_t u32Version;
+ uint32_t u32Alignment; /**< structure size alignment. */
+
+ /**
+ * Write to a CMOS register and update the checksum if necessary.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the RTC.
+ * @param iReg The CMOS register index.
+ * @param u8Value The CMOS register value.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value));
+
+ /**
+ * Read a CMOS register.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the RTC.
+ * @param iReg The CMOS register index.
+ * @param pu8Value Where to store the CMOS register value.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRead,(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value));
+
+} PDMRTCREG;
+/** Pointer to a RTC registration structure. */
+typedef PDMRTCREG *PPDMRTCREG;
+/** Pointer to a const RTC registration structure. */
+typedef const PDMRTCREG *PCPDMRTCREG;
+
+/** Current PDMRTCREG version number. */
+#define PDM_RTCREG_VERSION PDM_VERSION_MAKE(0xffe9, 1, 0)
+
+
+/**
+ * RTC device helpers.
+ */
+typedef struct PDMRTCHLP
+{
+ /** Structure version. PDM_RTCHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /* to-be-defined */
+
+} PDMRTCHLP;
+/** Pointer to RTC helpers. */
+typedef PDMRTCHLP *PPDMRTCHLP;
+/** Pointer to const RTC helpers. */
+typedef const PDMRTCHLP *PCPDMRTCHLP;
+
+/** Current PDMRTCHLP version number. */
+#define PDM_RTCHLP_VERSION PDM_VERSION_MAKE(0xffe8, 1, 0)
+
+
+
+#ifdef IN_RING3
+
+/**
+ * PDM Device API.
+ */
+typedef struct PDMDEVHLPR3
+{
+ /** Structure version. PDM_DEVHLPR3_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Register a number of I/O ports with a device.
+ *
+ * These callbacks are of course for the host context (HC).
+ * Register HC handlers before guest context (GC) handlers! There must be a
+ * HC handler for every GC handler!
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the ports with.
+ * @param Port First port number in the range.
+ * @param cPorts Number of ports to register.
+ * @param pvUser User argument.
+ * @param pfnOut Pointer to function which is gonna handle OUT operations.
+ * @param pfnIn Pointer to function which is gonna handle IN operations.
+ * @param pfnOutStr Pointer to function which is gonna handle string OUT operations.
+ * @param pfnInStr Pointer to function which is gonna handle string IN operations.
+ * @param pszDesc Pointer to description string. This must not be freed.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIOPortRegister,(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTHCPTR pvUser,
+ PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn,
+ PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, const char *pszDesc));
+
+ /**
+ * Register a number of I/O ports with a device for RC.
+ *
+ * These callbacks are for the raw-mode context (RC). Register ring-3 context
+ * (R3) handlers before raw-mode context handlers! There must be a R3 handler
+ * for every RC handler!
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the ports with
+ * and which RC module to resolve the names
+ * against.
+ * @param Port First port number in the range.
+ * @param cPorts Number of ports to register.
+ * @param pvUser User argument.
+ * @param pszOut Name of the RC function which is gonna handle OUT operations.
+ * @param pszIn Name of the RC function which is gonna handle IN operations.
+ * @param pszOutStr Name of the RC function which is gonna handle string OUT operations.
+ * @param pszInStr Name of the RC function which is gonna handle string IN operations.
+ * @param pszDesc Pointer to description string. This must not be freed.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIOPortRegisterRC,(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTRCPTR pvUser,
+ const char *pszOut, const char *pszIn,
+ const char *pszOutStr, const char *pszInStr, const char *pszDesc));
+
+ /**
+ * Register a number of I/O ports with a device.
+ *
+ * These callbacks are of course for the ring-0 host context (R0).
+ * Register R3 (HC) handlers before R0 (R0) handlers! There must be a R3 (HC) handler for every R0 handler!
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the ports with.
+ * @param Port First port number in the range.
+ * @param cPorts Number of ports to register.
+ * @param pvUser User argument. (if pointer, then it must be in locked memory!)
+ * @param pszOut Name of the R0 function which is gonna handle OUT operations.
+ * @param pszIn Name of the R0 function which is gonna handle IN operations.
+ * @param pszOutStr Name of the R0 function which is gonna handle string OUT operations.
+ * @param pszInStr Name of the R0 function which is gonna handle string IN operations.
+ * @param pszDesc Pointer to description string. This must not be freed.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIOPortRegisterR0,(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTR0PTR pvUser,
+ const char *pszOut, const char *pszIn,
+ const char *pszOutStr, const char *pszInStr, const char *pszDesc));
+
+ /**
+ * Deregister I/O ports.
+ *
+ * This naturally affects both guest context (GC), ring-0 (R0) and ring-3 (R3/HC) handlers.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance owning the ports.
+ * @param Port First port number in the range.
+ * @param cPorts Number of ports to deregister.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIOPortDeregister,(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts));
+
+ /**
+ * Register a Memory Mapped I/O (MMIO) region.
+ *
+ * These callbacks are of course for the ring-3 context (R3). Register HC
+ * handlers before raw-mode context (RC) and ring-0 context (R0) handlers! There
+ * must be a R3 handler for every RC and R0 handler!
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the MMIO with.
+ * @param GCPhysStart First physical address in the range.
+ * @param cbRange The size of the range (in bytes).
+ * @param pvUser User argument.
+ * @param pfnWrite Pointer to function which is gonna handle Write operations.
+ * @param pfnRead Pointer to function which is gonna handle Read operations.
+ * @param pfnFill Pointer to function which is gonna handle Fill/memset operations. (optional)
+ * @param fFlags Flags, IOMMMIO_FLAGS_XXX.
+ * @param pszDesc Pointer to description string. This must not be freed.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMMIORegister,(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTHCPTR pvUser,
+ PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead, PFNIOMMMIOFILL pfnFill,
+ uint32_t fFlags, const char *pszDesc));
+
+ /**
+ * Register a Memory Mapped I/O (MMIO) region for GC.
+ *
+ * These callbacks are for the raw-mode context (RC). Register ring-3 context
+ * (R3) handlers before guest context handlers! There must be a R3 handler for
+ * every RC handler!
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the MMIO with.
+ * @param GCPhysStart First physical address in the range.
+ * @param cbRange The size of the range (in bytes).
+ * @param pvUser User argument.
+ * @param pszWrite Name of the RC function which is gonna handle Write operations.
+ * @param pszRead Name of the RC function which is gonna handle Read operations.
+ * @param pszFill Name of the RC function which is gonna handle Fill/memset operations. (optional)
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMMIORegisterRC,(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTRCPTR pvUser,
+ const char *pszWrite, const char *pszRead, const char *pszFill));
+
+ /**
+ * Register a Memory Mapped I/O (MMIO) region for R0.
+ *
+ * These callbacks are for the ring-0 host context (R0). Register ring-3
+ * constext (R3) handlers before R0 handlers! There must be a R3 handler for
+ * every R0 handler!
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the MMIO with.
+ * @param GCPhysStart First physical address in the range.
+ * @param cbRange The size of the range (in bytes).
+ * @param pvUser User argument. (if pointer, then it must be in locked memory!)
+ * @param pszWrite Name of the RC function which is gonna handle Write operations.
+ * @param pszRead Name of the RC function which is gonna handle Read operations.
+ * @param pszFill Name of the RC function which is gonna handle Fill/memset operations. (optional)
+ * @param pszDesc Obsolete. NULL is fine.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMMIORegisterR0,(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTR0PTR pvUser,
+ const char *pszWrite, const char *pszRead, const char *pszFill));
+
+ /**
+ * Deregister a Memory Mapped I/O (MMIO) region.
+ *
+ * This naturally affects both guest context (GC), ring-0 (R0) and ring-3 (R3/HC) handlers.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance owning the MMIO region(s).
+ * @param GCPhysStart First physical address in the range.
+ * @param cbRange The size of the range (in bytes).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMMIODeregister,(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange));
+
+ /**
+ * Allocate and register a MMIO2 region.
+ *
+ * As mentioned elsewhere, MMIO2 is just RAM spelled differently. It's
+ * RAM associated with a device. It is also non-shared memory with a
+ * permanent ring-3 mapping and page backing (presently).
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance.
+ * @param iRegion The region number. Use the PCI region number as
+ * this must be known to the PCI bus device too. If
+ * it's not associated with the PCI device, then
+ * any number up to UINT8_MAX is fine.
+ * @param cb The size (in bytes) of the region.
+ * @param fFlags Reserved for future use, must be zero.
+ * @param ppv Where to store the address of the ring-3 mapping
+ * of the memory.
+ * @param pszDesc Pointer to description string. This must not be
+ * freed.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMMIO2Register,(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc));
+
+ /**
+ * Deregisters and frees a MMIO2 region.
+ *
+ * Any physical (and virtual) access handlers registered for the region must
+ * be deregistered before calling this function.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iRegion The region number used during registration.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMMIO2Deregister,(PPDMDEVINS pDevIns, uint32_t iRegion));
+
+ /**
+ * Maps a MMIO2 region into the physical memory space.
+ *
+ * A MMIO2 range may overlap with base memory if a lot of RAM
+ * is configured for the VM, in which case we'll drop the base
+ * memory pages. Presently we will make no attempt to preserve
+ * anything that happens to be present in the base memory that
+ * is replaced, this is of course incorrectly but it's too much
+ * effort.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iRegion The region number used during registration.
+ * @param GCPhys The physical address to map it at.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMMIO2Map,(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys));
+
+ /**
+ * Unmaps a MMIO2 region previously mapped using pfnMMIO2Map.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iRegion The region number used during registration.
+ * @param GCPhys The physical address it's currently mapped at.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMMIO2Unmap,(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys));
+
+ /**
+ * Maps a portion of an MMIO2 region into the hypervisor region.
+ *
+ * Callers of this API must never deregister the MMIO2 region before the
+ * VM is powered off.
+ *
+ * @return VBox status code.
+ * @param pDevIns The device owning the MMIO2 memory.
+ * @param iRegion The region.
+ * @param off The offset into the region. Will be rounded down
+ * to closest page boundary.
+ * @param cb The number of bytes to map. Will be rounded up
+ * to the closest page boundary.
+ * @param pszDesc Mapping description.
+ * @param pRCPtr Where to store the RC address.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMMHyperMapMMIO2,(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb,
+ const char *pszDesc, PRTRCPTR pRCPtr));
+
+ /**
+ * Maps a portion of an MMIO2 region into kernel space (host).
+ *
+ * The kernel mapping will become invalid when the MMIO2 memory is deregistered
+ * or the VM is terminated.
+ *
+ * @return VBox status code.
+ * @param pDevIns The device owning the MMIO2 memory.
+ * @param iRegion The region.
+ * @param off The offset into the region. Must be page
+ * aligned.
+ * @param cb The number of bytes to map. Must be page
+ * aligned.
+ * @param pszDesc Mapping description.
+ * @param pR0Ptr Where to store the R0 address.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMMIO2MapKernel,(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb,
+ const char *pszDesc, PRTR0PTR pR0Ptr));
+
+ /**
+ * Register a ROM (BIOS) region.
+ *
+ * It goes without saying that this is read-only memory. The memory region must be
+ * in unassigned memory. I.e. from the top of the address space or on the PC in
+ * the 0xa0000-0xfffff range.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance owning the ROM region.
+ * @param GCPhysStart First physical address in the range.
+ * Must be page aligned!
+ * @param cbRange The size of the range (in bytes).
+ * Must be page aligned!
+ * @param pvBinary Pointer to the binary data backing the ROM image.
+ * @param cbBinary The size of the binary pointer. This must
+ * be equal or smaller than @a cbRange.
+ * @param fFlags Shadow ROM flags, PGMPHYS_ROM_FLAGS_* in pgm.h.
+ * @param pszDesc Pointer to description string. This must not be freed.
+ *
+ * @remark There is no way to remove the rom, automatically on device cleanup or
+ * manually from the device yet. At present I doubt we need such features...
+ */
+ DECLR3CALLBACKMEMBER(int, pfnROMRegister,(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange,
+ const void *pvBinary, uint32_t cbBinary, uint32_t fFlags, const char *pszDesc));
+
+ /**
+ * Changes the protection of shadowed ROM mapping.
+ *
+ * This is intented for use by the system BIOS, chipset or device in question to
+ * change the protection of shadowed ROM code after init and on reset.
+ *
+ * @param pDevIns The device instance.
+ * @param GCPhysStart Where the mapping starts.
+ * @param cbRange The size of the mapping.
+ * @param enmProt The new protection type.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnROMProtectShadow,(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, PGMROMPROT enmProt));
+
+ /**
+ * Register a save state data unit.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance.
+ * @param pszName Data unit name.
+ * @param uInstance The instance identifier of the data unit.
+ * This must together with the name be unique.
+ * @param uVersion Data layout version number.
+ * @param cbGuess The approximate amount of data in the unit.
+ * Only for progress indicators.
+ * @param pszBefore Name of data unit which we should be put in
+ * front of. Optional (NULL).
+ *
+ * @param pfnLivePrep Prepare live save callback, optional.
+ * @param pfnLiveExec Execute live save callback, optional.
+ * @param pfnLiveVote Vote live save callback, optional.
+ *
+ * @param pfnSavePrep Prepare save callback, optional.
+ * @param pfnSaveExec Execute save callback, optional.
+ * @param pfnSaveDone Done save callback, optional.
+ *
+ * @param pfnLoadPrep Prepare load callback, optional.
+ * @param pfnLoadExec Execute load callback, optional.
+ * @param pfnLoadDone Done load callback, optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSSMRegister,(PPDMDEVINS pDevIns, uint32_t uVersion, size_t cbGuess, const char *pszBefore,
+ PFNSSMDEVLIVEPREP pfnLivePrep, PFNSSMDEVLIVEEXEC pfnLiveExec, PFNSSMDEVLIVEVOTE pfnLiveVote,
+ PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
+ PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone));
+
+ /**
+ * Creates a timer.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance.
+ * @param enmClock The clock to use on this timer.
+ * @param pfnCallback Callback function.
+ * @param pvUser User argument for the callback.
+ * @param fFlags Flags, see TMTIMER_FLAGS_*.
+ * @param pszDesc Pointer to description string which must stay around
+ * until the timer is fully destroyed (i.e. a bit after TMTimerDestroy()).
+ * @param ppTimer Where to store the timer on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTMTimerCreate,(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, void *pvUser, uint32_t fFlags, const char *pszDesc, PPTMTIMERR3 ppTimer));
+
+ /**
+ * Get the real world UTC time adjusted for VM lag, user offset and warpdrive.
+ *
+ * @returns pTime.
+ * @param pDevIns The device instance.
+ * @param pTime Where to store the time.
+ */
+ DECLR3CALLBACKMEMBER(PRTTIMESPEC, pfnTMUtcNow,(PPDMDEVINS pDevIns, PRTTIMESPEC pTime));
+
+ /**
+ * Read physical memory.
+ *
+ * @returns VINF_SUCCESS (for now).
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysRead,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead));
+
+ /**
+ * Write to physical memory.
+ *
+ * @returns VINF_SUCCESS for now, and later maybe VERR_EM_MEMORY.
+ * @param pDevIns The device instance.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ * @thread Any thread, but the call may involve the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysWrite,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite));
+
+ /**
+ * Requests the mapping of a guest page into ring-3.
+ *
+ * When you're done with the page, call pfnPhysReleasePageMappingLock() ASAP to
+ * release it.
+ *
+ * This API will assume your intention is to write to the page, and will
+ * therefore replace shared and zero pages. If you do not intend to modify the
+ * page, use the pfnPhysGCPhys2CCPtrReadOnly() API.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_PGM_PHYS_PAGE_RESERVED it it's a valid page but has no physical
+ * backing or if the page has any active access handlers. The caller
+ * must fall back on using PGMR3PhysWriteExternal.
+ * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if it's not a valid physical address.
+ *
+ * @param pVM The VM handle.
+ * @param GCPhys The guest physical address of the page that
+ * should be mapped.
+ * @param fFlags Flags reserved for future use, MBZ.
+ * @param ppv Where to store the address corresponding to
+ * GCPhys.
+ * @param pLock Where to store the lock information that
+ * pfnPhysReleasePageMappingLock needs.
+ *
+ * @remark Avoid calling this API from within critical sections (other than the
+ * PGM one) because of the deadlock risk when we have to delegating the
+ * task to an EMT.
+ * @thread Any.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysGCPhys2CCPtr,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t fFlags, void **ppv, PPGMPAGEMAPLOCK pLock));
+
+ /**
+ * Requests the mapping of a guest page into ring-3, external threads.
+ *
+ * When you're done with the page, call pfnPhysReleasePageMappingLock() ASAP to
+ * release it.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_PGM_PHYS_PAGE_RESERVED it it's a valid page but has no physical
+ * backing or if the page as an active ALL access handler. The caller
+ * must fall back on using PGMPhysRead.
+ * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS if it's not a valid physical address.
+ *
+ * @param pDevIns The device instance.
+ * @param GCPhys The guest physical address of the page that
+ * should be mapped.
+ * @param fFlags Flags reserved for future use, MBZ.
+ * @param ppv Where to store the address corresponding to
+ * GCPhys.
+ * @param pLock Where to store the lock information that
+ * pfnPhysReleasePageMappingLock needs.
+ *
+ * @remark Avoid calling this API from within critical sections.
+ * @thread Any.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysGCPhys2CCPtrReadOnly,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t fFlags, void const **ppv, PPGMPAGEMAPLOCK pLock));
+
+ /**
+ * Release the mapping of a guest page.
+ *
+ * This is the counter part of pfnPhysGCPhys2CCPtr and
+ * pfnPhysGCPhys2CCPtrReadOnly.
+ *
+ * @param pDevIns The device instance.
+ * @param pLock The lock structure initialized by the mapping
+ * function.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnPhysReleasePageMappingLock,(PPDMDEVINS pDevIns, PPGMPAGEMAPLOCK pLock));
+
+ /**
+ * Read guest physical memory by virtual address.
+ *
+ * @param pDevIns The device instance.
+ * @param pvDst Where to put the read bits.
+ * @param GCVirtSrc Guest virtual address to start reading from.
+ * @param cb How many bytes to read.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysReadGCVirt,(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb));
+
+ /**
+ * Write to guest physical memory by virtual address.
+ *
+ * @param pDevIns The device instance.
+ * @param GCVirtDst Guest virtual address to write to.
+ * @param pvSrc What to write.
+ * @param cb How many bytes to write.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysWriteGCVirt,(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb));
+
+ /**
+ * Convert a guest virtual address to a guest physical address.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param GCPtr Guest virtual address.
+ * @param pGCPhys Where to store the GC physical address
+ * corresponding to GCPtr.
+ * @thread The emulation thread.
+ * @remark Careful with page boundaries.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPhysGCPtr2GCPhys, (PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys));
+
+ /**
+ * Allocate memory which is associated with current VM instance
+ * and automatically freed on it's destruction.
+ *
+ * @returns Pointer to allocated memory. The memory is *NOT* zero-ed.
+ * @param pDevIns The device instance.
+ * @param cb Number of bytes to allocate.
+ */
+ DECLR3CALLBACKMEMBER(void *, pfnMMHeapAlloc,(PPDMDEVINS pDevIns, size_t cb));
+
+ /**
+ * Allocate memory which is associated with current VM instance
+ * and automatically freed on it's destruction. The memory is ZEROed.
+ *
+ * @returns Pointer to allocated memory. The memory is *NOT* zero-ed.
+ * @param pDevIns The device instance.
+ * @param cb Number of bytes to allocate.
+ */
+ DECLR3CALLBACKMEMBER(void *, pfnMMHeapAllocZ,(PPDMDEVINS pDevIns, size_t cb));
+
+ /**
+ * Free memory allocated with pfnMMHeapAlloc() and pfnMMHeapAllocZ().
+ *
+ * @param pDevIns The device instance.
+ * @param pv Pointer to the memory to free.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnMMHeapFree,(PPDMDEVINS pDevIns, void *pv));
+
+ /**
+ * Gets the VM state.
+ *
+ * @returns VM state.
+ * @param pDevIns The device instance.
+ * @thread Any thread (just keep in mind that it's volatile info).
+ */
+ DECLR3CALLBACKMEMBER(VMSTATE, pfnVMState, (PPDMDEVINS pDevIns));
+
+ /**
+ * Checks if the VM was teleported and hasn't been fully resumed yet.
+ *
+ * @returns true / false.
+ * @param pDevIns The device instance.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnVMTeleportedAndNotFullyResumedYet,(PPDMDEVINS pDevIns));
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDevIns The device instance.
+ * @param rc VBox status code.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetError,(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...));
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDevIns The device instance.
+ * @param rc VBox status code.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetErrorV,(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetRuntimeError,(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetRuntimeErrorV,(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va));
+
+ /**
+ * Stops the VM and enters the debugger to look at the guest state.
+ *
+ * Use the PDMDeviceDBGFStop() inline function with the RT_SRC_POS macro instead of
+ * invoking this function directly.
+ *
+ * @returns VBox status code which must be passed up to the VMM.
+ * @param pDevIns The device instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine The linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ * @param pszFormat Message. (optional)
+ * @param args Message parameters.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFStopV,(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args));
+
+ /**
+ * Register a info handler with DBGF,
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pszName The identifier of the info.
+ * @param pszDesc The description of the info and any arguments
+ * the handler may take.
+ * @param pfnHandler The handler function to be called to display the
+ * info.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFInfoRegister,(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler));
+
+ /**
+ * Gets the trace buffer handle.
+ *
+ * This is used by the macros found in VBox/vmm/dbgftrace.h and is not
+ * really inteded for direct usage, thus no inline wrapper function.
+ *
+ * @returns Trace buffer handle or NIL_RTTRACEBUF.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(RTTRACEBUF, pfnDBGFTraceBuf,(PPDMDEVINS pDevIns));
+
+ /**
+ * Registers a statistics sample if statistics are enabled.
+ *
+ * @param pDevIns Device instance of the DMA.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is
+ * pointing at.
+ * @param pszName Sample name. The name is on this form
+ * "/<component>/<sample>". Further nesting is
+ * possible.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSTAMRegister,(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc));
+
+ /**
+ * Same as pfnSTAMRegister except that the name is specified in a
+ * RTStrPrintf like fashion.
+ *
+ * @returns VBox status.
+ * @param pDevIns Device instance of the DMA.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is
+ * pointing at.
+ * @param enmVisibility Visibility type specifying whether unused
+ * statistics should be visible or not.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ * @param pszName The sample name format string.
+ * @param ... Arguments to the format string.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSTAMRegisterF,(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...));
+
+ /**
+ * Same as pfnSTAMRegister except that the name is specified in a
+ * RTStrPrintfV like fashion.
+ *
+ * @returns VBox status.
+ * @param pDevIns Device instance of the DMA.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is
+ * pointing at.
+ * @param enmVisibility Visibility type specifying whether unused
+ * statistics should be visible or not.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ * @param pszName The sample name format string.
+ * @param args Arguments to the format string.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSTAMRegisterV,(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args));
+
+ /**
+ * Reads data via bus mastering, if enabled. If no bus mastering is available,
+ * this function does nothing and returns VINF_PGM_PCI_PHYS_READ_BM_DISABLED.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIPhysRead,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead));
+
+ /**
+ * Writes data via bus mastering, if enabled. If no bus mastering is available,
+ * this function does nothing and returns VINF_PGM_PCI_PHYS_WRITE_BM_DISABLED.
+ *
+ * @return IPRT status code.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIPhysWrite,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite));
+
+ /**
+ * Registers the device with the default PCI bus.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure.
+ * Any PCI enabled device must keep this in it's instance data!
+ * Fill in the PCI data config before registration, please.
+ * @remark This is the simple interface, a Ex interface will be created if
+ * more features are needed later.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIRegister,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev));
+
+ /**
+ * Initialize MSI support in a PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pMsiReg MSI registartion structure.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIRegisterMsi,(PPDMDEVINS pDevIns, PPDMMSIREG pMsiReg));
+
+ /**
+ * Registers a I/O region (memory mapped or I/O ports) for a PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iRegion The region number.
+ * @param cbRegion Size of the region.
+ * @param enmType PCI_ADDRESS_SPACE_MEM, PCI_ADDRESS_SPACE_IO or PCI_ADDRESS_SPACE_MEM_PREFETCH.
+ * @param pfnCallback Callback for doing the mapping.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIIORegionRegister,(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback));
+
+ /**
+ * Register PCI configuration space read/write callbacks.
+ *
+ * @param pDevIns The device instance.
+ * @param pPciDev The PCI device structure.
+ * If NULL the default PCI device for this device instance is used.
+ * @param pfnRead Pointer to the user defined PCI config read function.
+ * @param ppfnReadOld Pointer to function pointer which will receive the old (default)
+ * PCI config read function. This way, user can decide when (and if)
+ * to call default PCI config read function. Can be NULL.
+ * @param pfnWrite Pointer to the user defined PCI config write function.
+ * @param pfnWriteOld Pointer to function pointer which will receive the old (default)
+ * PCI config write function. This way, user can decide when (and if)
+ * to call default PCI config write function. Can be NULL.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(void, pfnPCISetConfigCallbacks,(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
+ PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld));
+
+ /**
+ * Set the IRQ for a PCI device.
+ *
+ * @param pDevIns The device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnPCISetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel));
+
+ /**
+ * Set the IRQ for a PCI device, but don't wait for EMT to process
+ * the request when not called from EMT.
+ *
+ * @param pDevIns The device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnPCISetIrqNoWait,(PPDMDEVINS pDevIns, int iIrq, int iLevel));
+
+ /**
+ * Set ISA IRQ for a device.
+ *
+ * @param pDevIns The device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnISASetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel));
+
+ /**
+ * Set the ISA IRQ for a device, but don't wait for EMT to process
+ * the request when not called from EMT.
+ *
+ * @param pDevIns The device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnISASetIrqNoWait,(PPDMDEVINS pDevIns, int iIrq, int iLevel));
+
+ /**
+ * Attaches a driver (chain) to the device.
+ *
+ * The first call for a LUN this will serve as a registartion of the LUN. The pBaseInterface and
+ * the pszDesc string will be registered with that LUN and kept around for PDMR3QueryDeviceLun().
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iLun The logical unit to attach.
+ * @param pBaseInterface Pointer to the base interface for that LUN. (device side / down)
+ * @param ppBaseInterface Where to store the pointer to the base interface. (driver side / up)
+ * @param pszDesc Pointer to a string describing the LUN. This string must remain valid
+ * for the live of the device instance.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDriverAttach,(PPDMDEVINS pDevIns, uint32_t iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc));
+
+ /**
+ * Create a queue.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param cbItem The size of a queue item.
+ * @param cItems The number of items in the queue.
+ * @param cMilliesInterval The number of milliseconds between polling the queue.
+ * If 0 then the emulation thread will be notified whenever an item arrives.
+ * @param pfnCallback The consumer function.
+ * @param fRZEnabled Set if the queue should work in RC and R0.
+ * @param pszName The queue base name. The instance number will be
+ * appended automatically.
+ * @param ppQueue Where to store the queue handle on success.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueueCreate,(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName, PPDMQUEUE *ppQueue));
+
+ /**
+ * Initializes a PDM critical section.
+ *
+ * The PDM critical sections are derived from the IPRT critical sections, but
+ * works in RC and R0 as well.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pCritSect Pointer to the critical section.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszNameFmt Format string for naming the critical section.
+ * For statistics and lock validation.
+ * @param va Arguments for the format string.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCritSectInit,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
+ const char *pszNameFmt, va_list va));
+
+ /**
+ * Gets the NOP critical section.
+ *
+ * @returns The ring-3 address of the NOP critical section.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(PPDMCRITSECT, pfnCritSectGetNop,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the NOP critical section.
+ *
+ * @returns The ring-0 address of the NOP critical section.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(R0PTRTYPE(PPDMCRITSECT), pfnCritSectGetNopR0,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the NOP critical section.
+ *
+ * @returns The raw-mode context address of the NOP critical section.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(RCPTRTYPE(PPDMCRITSECT), pfnCritSectGetNopRC,(PPDMDEVINS pDevIns));
+
+ /**
+ * Changes the device level critical section from the automatically created
+ * default to one desired by the device constructor.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pCritSect The critical section to use. NULL is not
+ * valid, instead use the NOP critical
+ * section.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetDeviceCritSect,(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect));
+
+ /**
+ * Creates a PDM thread.
+ *
+ * This differs from the RTThreadCreate() API in that PDM takes care of suspending,
+ * resuming, and destroying the thread as the VM state changes.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param ppThread Where to store the thread 'handle'.
+ * @param pvUser The user argument to the thread function.
+ * @param pfnThread The thread function.
+ * @param pfnWakeup The wakup callback. This is called on the EMT
+ * thread when a state change is pending.
+ * @param cbStack See RTThreadCreate.
+ * @param enmType See RTThreadCreate.
+ * @param pszName See RTThreadCreate.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnThreadCreate,(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
+ PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName));
+
+ /**
+ * Set up asynchronous handling of a suspend, reset or power off notification.
+ *
+ * This shall only be called when getting the notification. It must be called
+ * for each one.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pfnAsyncNotify The callback.
+ * @thread EMT(0)
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetAsyncNotification, (PPDMDEVINS pDevIns, PFNPDMDEVASYNCNOTIFY pfnAsyncNotify));
+
+ /**
+ * Notify EMT(0) that the device has completed the asynchronous notification
+ * handling.
+ *
+ * This can be called at any time, spurious calls will simply be ignored.
+ *
+ * @param pDevIns The device instance.
+ * @thread Any
+ */
+ DECLR3CALLBACKMEMBER(void, pfnAsyncNotificationCompleted, (PPDMDEVINS pDevIns));
+
+ /**
+ * Register the RTC device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pRtcReg Pointer to a RTC registration structure.
+ * @param ppRtcHlp Where to store the pointer to the helper
+ * functions.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRTCRegister,(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp));
+
+ /**
+ * Register the PCI Bus.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPciBusReg Pointer to PCI bus registration structure.
+ * @param ppPciHlpR3 Where to store the pointer to the PCI Bus
+ * helpers.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPCIBusRegister,(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3));
+
+ /**
+ * Register the PIC device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pPicReg Pointer to a PIC registration structure.
+ * @param ppPicHlpR3 Where to store the pointer to the PIC HC
+ * helpers.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPICRegister,(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3));
+
+ /**
+ * Register the APIC device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pApicReg Pointer to a APIC registration structure.
+ * @param ppApicHlpR3 Where to store the pointer to the APIC helpers.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAPICRegister,(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3));
+
+ /**
+ * Register the I/O APIC device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pIoApicReg Pointer to a I/O APIC registration structure.
+ * @param ppIoApicHlpR3 Where to store the pointer to the IOAPIC
+ * helpers.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIOAPICRegister,(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3));
+
+ /**
+ * Register the HPET device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pHpetReg Pointer to a HPET registration structure.
+ * @param ppHpetHlpR3 Where to store the pointer to the HPET
+ * helpers.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnHPETRegister,(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR3 *ppHpetHlpR3));
+
+ /**
+ * Register a raw PCI device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pHpetReg Pointer to a raw PCI registration structure.
+ * @param ppPciRawHlpR3 Where to store the pointer to the raw PCI
+ * device helpers.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPciRawRegister,(PPDMDEVINS pDevIns, PPDMPCIRAWREG pPciRawReg, PCPDMPCIRAWHLPR3 *ppPciRawHlpR3));
+
+ /**
+ * Register the DMA device.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pDmacReg Pointer to a DMAC registration structure.
+ * @param ppDmacHlp Where to store the pointer to the DMA helpers.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDMACRegister,(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp));
+
+ /**
+ * Register transfer function for DMA channel.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param uChannel Channel number.
+ * @param pfnTransferHandler Device specific transfer callback function.
+ * @param pvUser User pointer to pass to the callback.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDMARegister,(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser));
+
+ /**
+ * Read memory.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param uChannel Channel number.
+ * @param pvBuffer Pointer to target buffer.
+ * @param off DMA position.
+ * @param cbBlock Block size.
+ * @param pcbRead Where to store the number of bytes which was
+ * read. optional.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDMAReadMemory,(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead));
+
+ /**
+ * Write memory.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param uChannel Channel number.
+ * @param pvBuffer Memory to write.
+ * @param off DMA position.
+ * @param cbBlock Block size.
+ * @param pcbWritten Where to store the number of bytes which was
+ * written. optional.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDMAWriteMemory,(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten));
+
+ /**
+ * Set the DREQ line.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance.
+ * @param uChannel Channel number.
+ * @param uLevel Level of the line.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDMASetDREQ,(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel));
+
+ /**
+ * Get channel mode.
+ *
+ * @returns Channel mode. See specs.
+ * @param pDevIns The device instance.
+ * @param uChannel Channel number.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(uint8_t, pfnDMAGetChannelMode,(PPDMDEVINS pDevIns, unsigned uChannel));
+
+ /**
+ * Schedule DMA execution.
+ *
+ * @param pDevIns The device instance.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnDMASchedule,(PPDMDEVINS pDevIns));
+
+ /**
+ * Write CMOS value and update the checksum(s).
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iReg The CMOS register index.
+ * @param u8Value The CMOS register value.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCMOSWrite,(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value));
+
+ /**
+ * Read CMOS value.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param iReg The CMOS register index.
+ * @param pu8Value Where to store the CMOS register value.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCMOSRead,(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value));
+
+ /**
+ * Assert that the current thread is the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDevIns The device instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine The linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertEMT,(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Assert that the current thread is NOT the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDevIns The device instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine The linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertOther,(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Resolves the symbol for a raw-mode context interface.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pvInterface The interface structure.
+ * @param cbInterface The size of the interface structure.
+ * @param pszSymPrefix What to prefix the symbols in the list with
+ * before resolving them. This must start with
+ * 'dev' and contain the driver name.
+ * @param pszSymList List of symbols corresponding to the interface.
+ * There is generally a there is generally a define
+ * holding this list associated with the interface
+ * definition (INTERFACE_SYM_LIST). For more
+ * details see PDMR3LdrGetInterfaceSymbols.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLdrGetRCInterfaceSymbols,(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
+ const char *pszSymPrefix, const char *pszSymList));
+
+ /**
+ * Resolves the symbol for a ring-0 context interface.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pvInterface The interface structure.
+ * @param cbInterface The size of the interface structure.
+ * @param pszSymPrefix What to prefix the symbols in the list with
+ * before resolving them. This must start with
+ * 'dev' and contain the driver name.
+ * @param pszSymList List of symbols corresponding to the interface.
+ * There is generally a there is generally a define
+ * holding this list associated with the interface
+ * definition (INTERFACE_SYM_LIST). For more
+ * details see PDMR3LdrGetInterfaceSymbols.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLdrGetR0InterfaceSymbols,(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
+ const char *pszSymPrefix, const char *pszSymList));
+
+ /**
+ * Call the ring-0 request handler routine of the device.
+ *
+ * For this to work, the device must be ring-0 enabled and export a request
+ * handler function. The name of the function must be the device name in
+ * the PDMDRVREG struct prefixed with 'drvR0' and suffixed with
+ * 'ReqHandler'. The device name will be captialized. It shall take the
+ * exact same arguments as this function and be declared using
+ * PDMBOTHCBDECL. See FNPDMDEVREQHANDLERR0.
+ *
+ * Unlike PDMDrvHlpCallR0, this is current unsuitable for more than a call
+ * or two as the handler address will be resolved on each invocation. This
+ * is the reason for the EMT only restriction as well.
+ *
+ * @returns VBox status code.
+ * @retval VERR_SYMBOL_NOT_FOUND if the device doesn't export the required
+ * handler function.
+ * @retval VERR_ACCESS_DENIED if the device isn't ring-0 capable.
+ *
+ * @param pDevIns The device instance.
+ * @param uOperation The operation to perform.
+ * @param u64Arg 64-bit integer argument.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCallR0,(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg));
+
+ /** Space reserved for future members.
+ * @{ */
+ DECLR3CALLBACKMEMBER(void, pfnReserved1,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved2,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved3,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved4,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved5,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved6,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved7,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved8,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved9,(void));
+ DECLR3CALLBACKMEMBER(void, pfnReserved10,(void));
+ /** @} */
+
+
+ /** API available to trusted devices only.
+ *
+ * These APIs are providing unrestricted access to the guest and the VM,
+ * or they are interacting intimately with PDM.
+ *
+ * @{
+ */
+ /**
+ * Gets the VM handle. Restricted API.
+ *
+ * @returns VM Handle.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(PVM, pfnGetVM,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the VMCPU handle. Restricted API.
+ *
+ * @returns VMCPU Handle.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(PVMCPU, pfnGetVMCPU,(PPDMDEVINS pDevIns));
+
+ /**
+ * Registers the VMM device heap
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param GCPhys The physical address.
+ * @param pvHeap Ring 3 heap pointer.
+ * @param cbSize Size of the heap.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegisterVMMDevHeap,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize));
+
+ /**
+ * Unregisters the VMM device heap
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param GCPhys The physical address.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUnregisterVMMDevHeap,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys));
+
+ /**
+ * Resets the VM.
+ *
+ * @returns The appropriate VBox status code to pass around on reset.
+ * @param pDevIns The device instance.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMReset,(PPDMDEVINS pDevIns));
+
+ /**
+ * Suspends the VM.
+ *
+ * @returns The appropriate VBox status code to pass around on suspend.
+ * @param pDevIns The device instance.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSuspend,(PPDMDEVINS pDevIns));
+
+ /**
+ * Suspends, saves and powers off the VM.
+ *
+ * @returns The appropriate VBox status code to pass around.
+ * @param pDevIns The device instance.
+ * @thread An emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSuspendSaveAndPowerOff,(PPDMDEVINS pDevIns));
+
+ /**
+ * Power off the VM.
+ *
+ * @returns The appropriate VBox status code to pass around on power off.
+ * @param pDevIns The device instance.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMPowerOff,(PPDMDEVINS pDevIns));
+
+ /**
+ * Checks if the Gate A20 is enabled or not.
+ *
+ * @returns true if A20 is enabled.
+ * @returns false if A20 is disabled.
+ * @param pDevIns The device instance.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnA20IsEnabled,(PPDMDEVINS pDevIns));
+
+ /**
+ * Enables or disables the Gate A20.
+ *
+ * @param pDevIns The device instance.
+ * @param fEnable Set this flag to enable the Gate A20; clear it
+ * to disable.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnA20Set,(PPDMDEVINS pDevIns, bool fEnable));
+
+ /**
+ * Get the specified CPUID leaf for the virtual CPU associated with the calling
+ * thread.
+ *
+ * @param pDevIns The device instance.
+ * @param iLeaf The CPUID leaf to get.
+ * @param pEax Where to store the EAX value.
+ * @param pEbx Where to store the EBX value.
+ * @param pEcx Where to store the ECX value.
+ * @param pEdx Where to store the EDX value.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnGetCpuId,(PPDMDEVINS pDevIns, uint32_t iLeaf, uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx));
+
+ /**
+ * Get the current virtual clock time in a VM. The clock frequency must be
+ * queried separately.
+ *
+ * @returns Current clock time.
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTMTimeVirtGet,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the frequency of the virtual clock.
+ *
+ * @returns The clock frequency (not variable at run-time).
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTMTimeVirtGetFreq,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the current virtual clock time in a VM, in nanoseconds.
+ *
+ * @returns Current clock time (in ns).
+ * @param pDevIns The device instance.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTMTimeVirtGetNano,(PPDMDEVINS pDevIns));
+
+ /** @} */
+
+ /** Just a safety precaution. (PDM_DEVHLPR3_VERSION) */
+ uint32_t u32TheEnd;
+} PDMDEVHLPR3;
+#endif /* !IN_RING3 */
+/** Pointer to the R3 PDM Device API. */
+typedef R3PTRTYPE(struct PDMDEVHLPR3 *) PPDMDEVHLPR3;
+/** Pointer to the R3 PDM Device API, const variant. */
+typedef R3PTRTYPE(const struct PDMDEVHLPR3 *) PCPDMDEVHLPR3;
+
+/** Current PDMDEVHLPR3 version number. */
+#define PDM_DEVHLPR3_VERSION PDM_VERSION_MAKE(0xffe7, 9, 0)
+
+
+/**
+ * PDM Device API - RC Variant.
+ */
+typedef struct PDMDEVHLPRC
+{
+ /** Structure version. PDM_DEVHLPRC_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Reads data via bus mastering, if enabled. If no bus mastering is available,
+ * this function does nothing and returns VINF_PGM_PCI_PHYS_READ_BM_DISABLED.
+ *
+ * @return IPRT status code.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnPCIDevPhysRead,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead));
+
+ /**
+ * Writes data via bus mastering, if enabled. If no bus mastering is available,
+ * this function does nothing and returns VINF_PGM_PCI_PHYS_WRITE_BM_DISABLED.
+ *
+ * @return IPRT status code.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnPCIDevPhysWrite,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite));
+
+ /**
+ * Set the IRQ for a PCI device.
+ *
+ * @param pDevIns Device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnPCISetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel));
+
+ /**
+ * Set ISA IRQ for a device.
+ *
+ * @param pDevIns Device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLRCCALLBACKMEMBER(void, pfnISASetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel));
+
+ /**
+ * Read physical memory.
+ *
+ * @returns VINF_SUCCESS (for now).
+ * @param pDevIns Device instance.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnPhysRead,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead));
+
+ /**
+ * Write to physical memory.
+ *
+ * @returns VINF_SUCCESS for now, and later maybe VERR_EM_MEMORY.
+ * @param pDevIns Device instance.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnPhysWrite,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite));
+
+ /**
+ * Checks if the Gate A20 is enabled or not.
+ *
+ * @returns true if A20 is enabled.
+ * @returns false if A20 is disabled.
+ * @param pDevIns Device instance.
+ * @thread The emulation thread.
+ */
+ DECLRCCALLBACKMEMBER(bool, pfnA20IsEnabled,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the VM state.
+ *
+ * @returns VM state.
+ * @param pDevIns The device instance.
+ * @thread Any thread (just keep in mind that it's volatile info).
+ */
+ DECLRCCALLBACKMEMBER(VMSTATE, pfnVMState, (PPDMDEVINS pDevIns));
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDrvIns Driver instance.
+ * @param rc VBox status code.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnVMSetError,(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...));
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDrvIns Driver instance.
+ * @param rc VBox status code.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnVMSetErrorV,(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnVMSetRuntimeError,(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnVMSetRuntimeErrorV,(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va));
+
+ /**
+ * Set parameters for pending MMIO patch operation
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance.
+ * @param GCPhys MMIO physical address
+ * @param pCachedData GC pointer to cached data
+ */
+ DECLRCCALLBACKMEMBER(int, pfnPATMSetMMIOPatchInfo,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPTR pCachedData));
+
+ /**
+ * Gets the VM handle. Restricted API.
+ *
+ * @returns VM Handle.
+ * @param pDevIns Device instance.
+ */
+ DECLRCCALLBACKMEMBER(PVM, pfnGetVM,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the VMCPU handle. Restricted API.
+ *
+ * @returns VMCPU Handle.
+ * @param pDevIns The device instance.
+ */
+ DECLRCCALLBACKMEMBER(PVMCPU, pfnGetVMCPU,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the current virtual clock time in a VM. The clock frequency must be
+ * queried separately.
+ *
+ * @returns Current clock time.
+ * @param pDevIns The device instance.
+ */
+ DECLRCCALLBACKMEMBER(uint64_t, pfnTMTimeVirtGet,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the frequency of the virtual clock.
+ *
+ * @returns The clock frequency (not variable at run-time).
+ * @param pDevIns The device instance.
+ */
+ DECLRCCALLBACKMEMBER(uint64_t, pfnTMTimeVirtGetFreq,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the current virtual clock time in a VM, in nanoseconds.
+ *
+ * @returns Current clock time (in ns).
+ * @param pDevIns The device instance.
+ */
+ DECLRCCALLBACKMEMBER(uint64_t, pfnTMTimeVirtGetNano,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the trace buffer handle.
+ *
+ * This is used by the macros found in VBox/vmm/dbgftrace.h and is not
+ * really inteded for direct usage, thus no inline wrapper function.
+ *
+ * @returns Trace buffer handle or NIL_RTTRACEBUF.
+ * @param pDevIns The device instance.
+ */
+ DECLRCCALLBACKMEMBER(RTTRACEBUF, pfnDBGFTraceBuf,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMDEVHLPRC;
+/** Pointer PDM Device RC API. */
+typedef RCPTRTYPE(struct PDMDEVHLPRC *) PPDMDEVHLPRC;
+/** Pointer PDM Device RC API. */
+typedef RCPTRTYPE(const struct PDMDEVHLPRC *) PCPDMDEVHLPRC;
+
+/** Current PDMDEVHLP version number. */
+#define PDM_DEVHLPRC_VERSION PDM_VERSION_MAKE(0xffe6, 3, 0)
+
+
+/**
+ * PDM Device API - R0 Variant.
+ */
+typedef struct PDMDEVHLPR0
+{
+ /** Structure version. PDM_DEVHLPR0_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Reads data via bus mastering, if enabled. If no bus mastering is available,
+ * this function does nothing and returns VINF_PGM_PCI_PHYS_READ_BM_DISABLED.
+ *
+ * @return IPRT status code.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPCIPhysRead,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead));
+
+ /**
+ * Writes data via bus mastering, if enabled. If no bus mastering is available,
+ * this function does nothing and returns VINF_PGM_PCI_PHYS_WRITE_BM_DISABLED.
+ *
+ * @return IPRT status code.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPCIPhysWrite,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite));
+
+ /**
+ * Set the IRQ for a PCI device.
+ *
+ * @param pDevIns Device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnPCISetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel));
+
+ /**
+ * Set ISA IRQ for a device.
+ *
+ * @param pDevIns Device instance.
+ * @param iIrq IRQ number to set.
+ * @param iLevel IRQ level. See the PDM_IRQ_LEVEL_* \#defines.
+ * @thread Any thread, but will involve the emulation thread.
+ */
+ DECLR0CALLBACKMEMBER(void, pfnISASetIrq,(PPDMDEVINS pDevIns, int iIrq, int iLevel));
+
+ /**
+ * Read physical memory.
+ *
+ * @returns VINF_SUCCESS (for now).
+ * @param pDevIns Device instance.
+ * @param GCPhys Physical address start reading from.
+ * @param pvBuf Where to put the read bits.
+ * @param cbRead How many bytes to read.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPhysRead,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead));
+
+ /**
+ * Write to physical memory.
+ *
+ * @returns VINF_SUCCESS for now, and later maybe VERR_EM_MEMORY.
+ * @param pDevIns Device instance.
+ * @param GCPhys Physical address to write to.
+ * @param pvBuf What to write.
+ * @param cbWrite How many bytes to write.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPhysWrite,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite));
+
+ /**
+ * Checks if the Gate A20 is enabled or not.
+ *
+ * @returns true if A20 is enabled.
+ * @returns false if A20 is disabled.
+ * @param pDevIns Device instance.
+ * @thread The emulation thread.
+ */
+ DECLR0CALLBACKMEMBER(bool, pfnA20IsEnabled,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the VM state.
+ *
+ * @returns VM state.
+ * @param pDevIns The device instance.
+ * @thread Any thread (just keep in mind that it's volatile info).
+ */
+ DECLR0CALLBACKMEMBER(VMSTATE, pfnVMState, (PPDMDEVINS pDevIns));
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDrvIns Driver instance.
+ * @param rc VBox status code.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnVMSetError,(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...));
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDrvIns Driver instance.
+ * @param rc VBox status code.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnVMSetErrorV,(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnVMSetRuntimeError,(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnVMSetRuntimeErrorV,(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va));
+
+ /**
+ * Set parameters for pending MMIO patch operation
+ *
+ * @returns rc.
+ * @param pDevIns Device instance.
+ * @param GCPhys MMIO physical address
+ * @param pCachedData GC pointer to cached data
+ */
+ DECLR0CALLBACKMEMBER(int, pfnPATMSetMMIOPatchInfo,(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPTR pCachedData));
+
+ /**
+ * Gets the VM handle. Restricted API.
+ *
+ * @returns VM Handle.
+ * @param pDevIns Device instance.
+ */
+ DECLR0CALLBACKMEMBER(PVM, pfnGetVM,(PPDMDEVINS pDevIns));
+
+ /**
+ * Checks if our current CPU state allows for IO block emulation fallback to the recompiler
+ *
+ * @returns true = yes, false = no
+ * @param pDevIns Device instance.
+ */
+ DECLR0CALLBACKMEMBER(bool, pfnCanEmulateIoBlock,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the VMCPU handle. Restricted API.
+ *
+ * @returns VMCPU Handle.
+ * @param pDevIns The device instance.
+ */
+ DECLR0CALLBACKMEMBER(PVMCPU, pfnGetVMCPU,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the current virtual clock time in a VM. The clock frequency must be
+ * queried separately.
+ *
+ * @returns Current clock time.
+ * @param pDevIns The device instance.
+ */
+ DECLR0CALLBACKMEMBER(uint64_t, pfnTMTimeVirtGet,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the frequency of the virtual clock.
+ *
+ * @returns The clock frequency (not variable at run-time).
+ * @param pDevIns The device instance.
+ */
+ DECLR0CALLBACKMEMBER(uint64_t, pfnTMTimeVirtGetFreq,(PPDMDEVINS pDevIns));
+
+ /**
+ * Get the current virtual clock time in a VM, in nanoseconds.
+ *
+ * @returns Current clock time (in ns).
+ * @param pDevIns The device instance.
+ */
+ DECLR0CALLBACKMEMBER(uint64_t, pfnTMTimeVirtGetNano,(PPDMDEVINS pDevIns));
+
+ /**
+ * Gets the trace buffer handle.
+ *
+ * This is used by the macros found in VBox/vmm/dbgftrace.h and is not
+ * really inteded for direct usage, thus no inline wrapper function.
+ *
+ * @returns Trace buffer handle or NIL_RTTRACEBUF.
+ * @param pDevIns The device instance.
+ */
+ DECLR0CALLBACKMEMBER(RTTRACEBUF, pfnDBGFTraceBuf,(PPDMDEVINS pDevIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMDEVHLPR0;
+/** Pointer PDM Device R0 API. */
+typedef R0PTRTYPE(struct PDMDEVHLPR0 *) PPDMDEVHLPR0;
+/** Pointer PDM Device GC API. */
+typedef R0PTRTYPE(const struct PDMDEVHLPR0 *) PCPDMDEVHLPR0;
+
+/** Current PDMDEVHLP version number. */
+#define PDM_DEVHLPR0_VERSION PDM_VERSION_MAKE(0xffe5, 3, 0)
+
+
+
+/**
+ * PDM Device Instance.
+ */
+typedef struct PDMDEVINS
+{
+ /** Structure version. PDM_DEVINS_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Device instance number. */
+ uint32_t iInstance;
+
+ /** Pointer the GC PDM Device API. */
+ PCPDMDEVHLPRC pHlpRC;
+ /** Pointer to device instance data. */
+ RTRCPTR pvInstanceDataRC;
+ /** The critical section for the device, see pCritSectXR3. */
+ RCPTRTYPE(PPDMCRITSECT) pCritSectRoRC;
+ /** Alignment padding. */
+ RTRCPTR pAlignmentRC;
+
+ /** Pointer the R0 PDM Device API. */
+ PCPDMDEVHLPR0 pHlpR0;
+ /** Pointer to device instance data (R0). */
+ RTR0PTR pvInstanceDataR0;
+ /** The critical section for the device, see pCritSectXR3. */
+ R0PTRTYPE(PPDMCRITSECT) pCritSectRoR0;
+
+ /** Pointer the HC PDM Device API. */
+ PCPDMDEVHLPR3 pHlpR3;
+ /** Pointer to device instance data. */
+ RTR3PTR pvInstanceDataR3;
+ /** The critical section for the device.
+ *
+ * TM and IOM will enter this critical section before calling into the device
+ * code. PDM will when doing power on, power off, reset, suspend and resume
+ * notifications. SSM will currently not, but this will be changed later on.
+ *
+ * The device gets a critical section automatically assigned to it before
+ * the constructor is called. If the constructor wishes to use a different
+ * critical section, it calls PDMDevHlpSetDeviceCritSect() to change it
+ * very early on.
+ */
+ R3PTRTYPE(PPDMCRITSECT) pCritSectRoR3;
+
+ /** Pointer to device registration structure. */
+ R3PTRTYPE(PCPDMDEVREG) pReg;
+ /** Configuration handle. */
+ R3PTRTYPE(PCFGMNODE) pCfg;
+
+ /** The base interface of the device.
+ *
+ * The device constructor initializes this if it has any
+ * device level interfaces to export. To obtain this interface
+ * call PDMR3QueryDevice(). */
+ PDMIBASE IBase;
+
+ /** Tracing indicator. */
+ uint32_t fTracing;
+ /** The tracing ID of this device. */
+ uint32_t idTracing;
+#if HC_ARCH_BITS == 32
+ /** Align the internal data more naturally. */
+ uint32_t au32Padding[HC_ARCH_BITS == 32 ? 13 : 0];
+#endif
+
+ /** Internal data. */
+ union
+ {
+#ifdef PDMDEVINSINT_DECLARED
+ PDMDEVINSINT s;
+#endif
+ uint8_t padding[HC_ARCH_BITS == 32 ? 72 : 112 + 0x28];
+ } Internal;
+
+ /** Device instance data. The size of this area is defined
+ * in the PDMDEVREG::cbInstanceData field. */
+ char achInstanceData[8];
+} PDMDEVINS;
+
+/** Current PDMDEVINS version number. */
+#define PDM_DEVINS_VERSION PDM_VERSION_MAKE(0xffe4, 3, 0)
+
+/** Converts a pointer to the PDMDEVINS::IBase to a pointer to PDMDEVINS. */
+#define PDMIBASE_2_PDMDEV(pInterface) ( (PPDMDEVINS)((char *)(pInterface) - RT_OFFSETOF(PDMDEVINS, IBase)) )
+
+/**
+ * Checks the structure versions of the device instance and device helpers,
+ * returning if they are incompatible.
+ *
+ * This is for use in the constructor.
+ *
+ * @param pDevIns The device instance pointer.
+ */
+#define PDMDEV_CHECK_VERSIONS_RETURN(pDevIns) \
+ do \
+ { \
+ PPDMDEVINS pDevInsTypeCheck = (pDevIns); NOREF(pDevInsTypeCheck); \
+ AssertLogRelMsgReturn(PDM_VERSION_ARE_COMPATIBLE((pDevIns)->u32Version, PDM_DEVINS_VERSION), \
+ ("DevIns=%#x mine=%#x\n", (pDevIns)->u32Version, PDM_DEVINS_VERSION), \
+ VERR_PDM_DEVINS_VERSION_MISMATCH); \
+ AssertLogRelMsgReturn(PDM_VERSION_ARE_COMPATIBLE((pDevIns)->pHlpR3->u32Version, PDM_DEVHLPR3_VERSION), \
+ ("DevHlp=%#x mine=%#x\n", (pDevIns)->pHlpR3->u32Version, PDM_DEVHLPR3_VERSION), \
+ VERR_PDM_DEVHLPR3_VERSION_MISMATCH); \
+ } while (0)
+
+/**
+ * Quietly checks the structure versions of the device instance and device
+ * helpers, returning if they are incompatible.
+ *
+ * This is for use in the destructor.
+ *
+ * @param pDevIns The device instance pointer.
+ */
+#define PDMDEV_CHECK_VERSIONS_RETURN_QUIET(pDevIns) \
+ do \
+ { \
+ PPDMDEVINS pDevInsTypeCheck = (pDevIns); NOREF(pDevInsTypeCheck); \
+ if (RT_UNLIKELY(!PDM_VERSION_ARE_COMPATIBLE((pDevIns)->u32Version, PDM_DEVINS_VERSION) )) \
+ return VERR_PDM_DEVINS_VERSION_MISMATCH; \
+ if (RT_UNLIKELY(!PDM_VERSION_ARE_COMPATIBLE((pDevIns)->pHlpR3->u32Version, PDM_DEVHLPR3_VERSION) )) \
+ return VERR_PDM_DEVHLPR3_VERSION_MISMATCH; \
+ } while (0)
+
+/**
+ * Wrapper around CFGMR3ValidateConfig for the root config for use in the
+ * constructor - returns on failure.
+ *
+ * This should be invoked after having initialized the instance data
+ * sufficiently for the correct operation of the destructor. The destructor is
+ * always called!
+ *
+ * @param pDevIns Pointer to the PDM device instance.
+ * @param pszValidValues Patterns describing the valid value names. See
+ * RTStrSimplePatternMultiMatch for details on the
+ * pattern syntax.
+ * @param pszValidNodes Patterns describing the valid node (key) names.
+ * Pass empty string if no valid nodes.
+ */
+#define PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, pszValidValues, pszValidNodes) \
+ do \
+ { \
+ int rcValCfg = CFGMR3ValidateConfig((pDevIns)->pCfg, "/", pszValidValues, pszValidNodes, \
+ (pDevIns)->pReg->szName, (pDevIns)->iInstance); \
+ if (RT_FAILURE(rcValCfg)) \
+ return rcValCfg; \
+ } while (0)
+
+/** @def PDMDEV_ASSERT_EMT
+ * Assert that the current thread is the emulation thread.
+ */
+#ifdef VBOX_STRICT
+# define PDMDEV_ASSERT_EMT(pDevIns) pDevIns->pHlpR3->pfnAssertEMT(pDevIns, __FILE__, __LINE__, __FUNCTION__)
+#else
+# define PDMDEV_ASSERT_EMT(pDevIns) do { } while (0)
+#endif
+
+/** @def PDMDEV_ASSERT_OTHER
+ * Assert that the current thread is NOT the emulation thread.
+ */
+#ifdef VBOX_STRICT
+# define PDMDEV_ASSERT_OTHER(pDevIns) pDevIns->pHlpR3->pfnAssertOther(pDevIns, __FILE__, __LINE__, __FUNCTION__)
+#else
+# define PDMDEV_ASSERT_OTHER(pDevIns) do { } while (0)
+#endif
+
+/** @def PDMDEV_ASSERT_VMLOCK_OWNER
+ * Assert that the current thread is owner of the VM lock.
+ */
+#ifdef VBOX_STRICT
+# define PDMDEV_ASSERT_VMLOCK_OWNER(pDevIns) pDevIns->pHlpR3->pfnAssertVMLock(pDevIns, __FILE__, __LINE__, __FUNCTION__)
+#else
+# define PDMDEV_ASSERT_VMLOCK_OWNER(pDevIns) do { } while (0)
+#endif
+
+/** @def PDMDEV_SET_ERROR
+ * Set the VM error. See PDMDevHlpVMSetError() for printf like message formatting.
+ */
+#define PDMDEV_SET_ERROR(pDevIns, rc, pszError) \
+ PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS, "%s", pszError)
+
+/** @def PDMDEV_SET_RUNTIME_ERROR
+ * Set the VM runtime error. See PDMDevHlpVMSetRuntimeError() for printf like message formatting.
+ */
+#define PDMDEV_SET_RUNTIME_ERROR(pDevIns, fFlags, pszErrorId, pszError) \
+ PDMDevHlpVMSetRuntimeError(pDevIns, fFlags, pszErrorId, "%s", pszError)
+
+/** @def PDMDEVINS_2_RCPTR
+ * Converts a PDM Device instance pointer a RC PDM Device instance pointer.
+ */
+#define PDMDEVINS_2_RCPTR(pDevIns) ( (RCPTRTYPE(PPDMDEVINS))((RTGCUINTPTR)(pDevIns)->pvInstanceDataRC - RT_OFFSETOF(PDMDEVINS, achInstanceData)) )
+
+/** @def PDMDEVINS_2_R3PTR
+ * Converts a PDM Device instance pointer a R3 PDM Device instance pointer.
+ */
+#define PDMDEVINS_2_R3PTR(pDevIns) ( (R3PTRTYPE(PPDMDEVINS))((RTHCUINTPTR)(pDevIns)->pvInstanceDataR3 - RT_OFFSETOF(PDMDEVINS, achInstanceData)) )
+
+/** @def PDMDEVINS_2_R0PTR
+ * Converts a PDM Device instance pointer a R0 PDM Device instance pointer.
+ */
+#define PDMDEVINS_2_R0PTR(pDevIns) ( (R0PTRTYPE(PPDMDEVINS))((RTR0UINTPTR)(pDevIns)->pvInstanceDataR0 - RT_OFFSETOF(PDMDEVINS, achInstanceData)) )
+
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnIOPortRegister
+ */
+DECLINLINE(int) PDMDevHlpIOPortRegister(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTHCPTR pvUser,
+ PFNIOMIOPORTOUT pfnOut, PFNIOMIOPORTIN pfnIn,
+ PFNIOMIOPORTOUTSTRING pfnOutStr, PFNIOMIOPORTINSTRING pfnInStr, const char *pszDesc)
+{
+ return pDevIns->pHlpR3->pfnIOPortRegister(pDevIns, Port, cPorts, pvUser, pfnOut, pfnIn, pfnOutStr, pfnInStr, pszDesc);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnIOPortRegisterRC
+ */
+DECLINLINE(int) PDMDevHlpIOPortRegisterRC(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTRCPTR pvUser,
+ const char *pszOut, const char *pszIn, const char *pszOutStr,
+ const char *pszInStr, const char *pszDesc)
+{
+ return pDevIns->pHlpR3->pfnIOPortRegisterRC(pDevIns, Port, cPorts, pvUser, pszOut, pszIn, pszOutStr, pszInStr, pszDesc);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnIOPortRegisterR0
+ */
+DECLINLINE(int) PDMDevHlpIOPortRegisterR0(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts, RTR0PTR pvUser,
+ const char *pszOut, const char *pszIn, const char *pszOutStr,
+ const char *pszInStr, const char *pszDesc)
+{
+ return pDevIns->pHlpR3->pfnIOPortRegisterR0(pDevIns, Port, cPorts, pvUser, pszOut, pszIn, pszOutStr, pszInStr, pszDesc);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnIOPortDeregister
+ */
+DECLINLINE(int) PDMDevHlpIOPortDeregister(PPDMDEVINS pDevIns, RTIOPORT Port, RTIOPORT cPorts)
+{
+ return pDevIns->pHlpR3->pfnIOPortDeregister(pDevIns, Port, cPorts);
+}
+
+/**
+ * Register a Memory Mapped I/O (MMIO) region.
+ *
+ * These callbacks are of course for the ring-3 context (R3). Register HC
+ * handlers before raw-mode context (RC) and ring-0 context (R0) handlers! There
+ * must be a R3 handler for every RC and R0 handler!
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the MMIO with.
+ * @param GCPhysStart First physical address in the range.
+ * @param cbRange The size of the range (in bytes).
+ * @param pvUser User argument.
+ * @param fFlags Flags, IOMMMIO_FLAGS_XXX.
+ * @param pfnWrite Pointer to function which is gonna handle Write operations.
+ * @param pfnRead Pointer to function which is gonna handle Read operations.
+ * @param pszDesc Pointer to description string. This must not be freed.
+ */
+DECLINLINE(int) PDMDevHlpMMIORegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTHCPTR pvUser,
+ uint32_t fFlags, PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead, const char *pszDesc)
+{
+ return pDevIns->pHlpR3->pfnMMIORegister(pDevIns, GCPhysStart, cbRange, pvUser, pfnWrite, pfnRead, NULL /*pfnFill*/,
+ fFlags, pszDesc);
+}
+
+/**
+ * Register a Memory Mapped I/O (MMIO) region for GC.
+ *
+ * These callbacks are for the raw-mode context (RC). Register ring-3 context
+ * (R3) handlers before guest context handlers! There must be a R3 handler for
+ * every RC handler!
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance to register the MMIO with.
+ * @param GCPhysStart First physical address in the range.
+ * @param cbRange The size of the range (in bytes).
+ * @param pvUser User argument.
+ * @param pszWrite Name of the RC function which is gonna handle Write operations.
+ * @param pszRead Name of the RC function which is gonna handle Read operations.
+ */
+DECLINLINE(int) PDMDevHlpMMIORegisterRC(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTRCPTR pvUser,
+ const char *pszWrite, const char *pszRead)
+{
+ return pDevIns->pHlpR3->pfnMMIORegisterRC(pDevIns, GCPhysStart, cbRange, pvUser, pszWrite, pszRead, NULL /*pszFill*/);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMIORegisterR0
+ */
+DECLINLINE(int) PDMDevHlpMMIORegisterR0(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTR0PTR pvUser,
+ const char *pszWrite, const char *pszRead)
+{
+ return pDevIns->pHlpR3->pfnMMIORegisterR0(pDevIns, GCPhysStart, cbRange, pvUser, pszWrite, pszRead, NULL /*pszFill*/);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMIORegister
+ */
+DECLINLINE(int) PDMDevHlpMMIORegisterEx(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTHCPTR pvUser,
+ uint32_t fFlags, PFNIOMMMIOWRITE pfnWrite, PFNIOMMMIOREAD pfnRead,
+ PFNIOMMMIOFILL pfnFill, const char *pszDesc)
+{
+ return pDevIns->pHlpR3->pfnMMIORegister(pDevIns, GCPhysStart, cbRange, pvUser, pfnWrite, pfnRead, pfnFill,
+ fFlags, pszDesc);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMIORegisterRC
+ */
+DECLINLINE(int) PDMDevHlpMMIORegisterRCEx(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTRCPTR pvUser,
+ const char *pszWrite, const char *pszRead, const char *pszFill)
+{
+ return pDevIns->pHlpR3->pfnMMIORegisterRC(pDevIns, GCPhysStart, cbRange, pvUser, pszWrite, pszRead, pszFill);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMIORegisterR0
+ */
+DECLINLINE(int) PDMDevHlpMMIORegisterR0Ex(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, RTR0PTR pvUser,
+ const char *pszWrite, const char *pszRead, const char *pszFill)
+{
+ return pDevIns->pHlpR3->pfnMMIORegisterR0(pDevIns, GCPhysStart, cbRange, pvUser, pszWrite, pszRead, pszFill);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMIODeregister
+ */
+DECLINLINE(int) PDMDevHlpMMIODeregister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange)
+{
+ return pDevIns->pHlpR3->pfnMMIODeregister(pDevIns, GCPhysStart, cbRange);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMIO2Register
+ */
+DECLINLINE(int) PDMDevHlpMMIO2Register(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc)
+{
+ return pDevIns->pHlpR3->pfnMMIO2Register(pDevIns, iRegion, cb, fFlags, ppv, pszDesc);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMIO2Deregister
+ */
+DECLINLINE(int) PDMDevHlpMMIO2Deregister(PPDMDEVINS pDevIns, uint32_t iRegion)
+{
+ return pDevIns->pHlpR3->pfnMMIO2Deregister(pDevIns, iRegion);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMIO2Map
+ */
+DECLINLINE(int) PDMDevHlpMMIO2Map(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
+{
+ return pDevIns->pHlpR3->pfnMMIO2Map(pDevIns, iRegion, GCPhys);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMIO2Unmap
+ */
+DECLINLINE(int) PDMDevHlpMMIO2Unmap(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys)
+{
+ return pDevIns->pHlpR3->pfnMMIO2Unmap(pDevIns, iRegion, GCPhys);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMHyperMapMMIO2
+ */
+DECLINLINE(int) PDMDevHlpMMHyperMapMMIO2(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb,
+ const char *pszDesc, PRTRCPTR pRCPtr)
+{
+ return pDevIns->pHlpR3->pfnMMHyperMapMMIO2(pDevIns, iRegion, off, cb, pszDesc, pRCPtr);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMIO2MapKernel
+ */
+DECLINLINE(int) PDMDevHlpMMIO2MapKernel(PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb,
+ const char *pszDesc, PRTR0PTR pR0Ptr)
+{
+ return pDevIns->pHlpR3->pfnMMIO2MapKernel(pDevIns, iRegion, off, cb, pszDesc, pR0Ptr);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnROMRegister
+ */
+DECLINLINE(int) PDMDevHlpROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange,
+ const void *pvBinary, uint32_t cbBinary, uint32_t fFlags, const char *pszDesc)
+{
+ return pDevIns->pHlpR3->pfnROMRegister(pDevIns, GCPhysStart, cbRange, pvBinary, cbBinary, fFlags, pszDesc);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnROMProtectShadow
+ */
+DECLINLINE(int) PDMDevHlpROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, PGMROMPROT enmProt)
+{
+ return pDevIns->pHlpR3->pfnROMProtectShadow(pDevIns, GCPhysStart, cbRange, enmProt);
+}
+
+/**
+ * Register a save state data unit.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance.
+ * @param uVersion Data layout version number.
+ * @param cbGuess The approximate amount of data in the unit.
+ * Only for progress indicators.
+ * @param pfnSaveExec Execute save callback, optional.
+ * @param pfnLoadExec Execute load callback, optional.
+ */
+DECLINLINE(int) PDMDevHlpSSMRegister(PPDMDEVINS pDevIns, uint32_t uVersion, size_t cbGuess,
+ PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVLOADEXEC pfnLoadExec)
+{
+ return pDevIns->pHlpR3->pfnSSMRegister(pDevIns, uVersion, cbGuess, NULL /*pszBefore*/,
+ NULL /*pfnLivePrep*/, NULL /*pfnLiveExec*/, NULL /*pfnLiveDone*/,
+ NULL /*pfnSavePrep*/, pfnSaveExec, NULL /*pfnSaveDone*/,
+ NULL /*pfnLoadPrep*/, pfnLoadExec, NULL /*pfnLoadDone*/);
+}
+
+/**
+ * Register a save state data unit with a live save callback as well.
+ *
+ * @returns VBox status.
+ * @param pDevIns The device instance.
+ * @param uVersion Data layout version number.
+ * @param cbGuess The approximate amount of data in the unit.
+ * Only for progress indicators.
+ * @param pfnLiveExec Execute live callback, optional.
+ * @param pfnSaveExec Execute save callback, optional.
+ * @param pfnLoadExec Execute load callback, optional.
+ */
+DECLINLINE(int) PDMDevHlpSSMRegister3(PPDMDEVINS pDevIns, uint32_t uVersion, size_t cbGuess,
+ FNSSMDEVLIVEEXEC pfnLiveExec, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVLOADEXEC pfnLoadExec)
+{
+ return pDevIns->pHlpR3->pfnSSMRegister(pDevIns, uVersion, cbGuess, NULL /*pszBefore*/,
+ NULL /*pfnLivePrep*/, pfnLiveExec, NULL /*pfnLiveDone*/,
+ NULL /*pfnSavePrep*/, pfnSaveExec, NULL /*pfnSaveDone*/,
+ NULL /*pfnLoadPrep*/, pfnLoadExec, NULL /*pfnLoadDone*/);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSSMRegister
+ */
+DECLINLINE(int) PDMDevHlpSSMRegisterEx(PPDMDEVINS pDevIns, uint32_t uVersion, size_t cbGuess, const char *pszBefore,
+ PFNSSMDEVLIVEPREP pfnLivePrep, PFNSSMDEVLIVEEXEC pfnLiveExec, PFNSSMDEVLIVEVOTE pfnLiveVote,
+ PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
+ PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone)
+{
+ return pDevIns->pHlpR3->pfnSSMRegister(pDevIns, uVersion, cbGuess, pszBefore,
+ pfnLivePrep, pfnLiveExec, pfnLiveVote,
+ pfnSavePrep, pfnSaveExec, pfnSaveDone,
+ pfnLoadPrep, pfnLoadExec, pfnLoadDone);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTMTimerCreate
+ */
+DECLINLINE(int) PDMDevHlpTMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, void *pvUser, uint32_t fFlags,
+ const char *pszDesc, PPTMTIMERR3 ppTimer)
+{
+ return pDevIns->pHlpR3->pfnTMTimerCreate(pDevIns, enmClock, pfnCallback, pvUser, fFlags, pszDesc, ppTimer);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTMUtcNow
+ */
+DECLINLINE(PRTTIMESPEC) PDMDevHlpTMUtcNow(PPDMDEVINS pDevIns, PRTTIMESPEC pTime)
+{
+ return pDevIns->pHlpR3->pfnTMUtcNow(pDevIns, pTime);
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysRead
+ */
+DECLINLINE(int) PDMDevHlpPhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysWrite
+ */
+DECLINLINE(int) PDMDevHlpPhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite);
+}
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysGCPhys2CCPtr
+ */
+DECLINLINE(int) PDMDevHlpPhysGCPhys2CCPtr(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t fFlags, void **ppv, PPGMPAGEMAPLOCK pLock)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysGCPhys2CCPtr(pDevIns, GCPhys, fFlags, ppv, pLock);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysGCPhys2CCPtrReadOnly
+ */
+DECLINLINE(int) PDMDevHlpPhysGCPhys2CCPtrReadOnly(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t fFlags, void const **ppv, PPGMPAGEMAPLOCK pLock)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnPhysGCPhys2CCPtrReadOnly(pDevIns, GCPhys, fFlags, ppv, pLock);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysReleasePageMappingLock
+ */
+DECLINLINE(void) PDMDevHlpPhysReleasePageMappingLock(PPDMDEVINS pDevIns, PPGMPAGEMAPLOCK pLock)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnPhysReleasePageMappingLock(pDevIns, pLock);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysReadGCVirt
+ */
+DECLINLINE(int) PDMDevHlpPhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
+{
+ return pDevIns->pHlpR3->pfnPhysReadGCVirt(pDevIns, pvDst, GCVirtSrc, cb);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysWriteGCVirt
+ */
+DECLINLINE(int) PDMDevHlpPhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
+{
+ return pDevIns->pHlpR3->pfnPhysWriteGCVirt(pDevIns, GCVirtDst, pvSrc, cb);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPhysGCPtr2GCPhys
+ */
+DECLINLINE(int) PDMDevHlpPhysGCPtr2GCPhys(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys)
+{
+ return pDevIns->pHlpR3->pfnPhysGCPtr2GCPhys(pDevIns, GCPtr, pGCPhys);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMHeapAlloc
+ */
+DECLINLINE(void *) PDMDevHlpMMHeapAlloc(PPDMDEVINS pDevIns, size_t cb)
+{
+ return pDevIns->pHlpR3->pfnMMHeapAlloc(pDevIns, cb);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMHeapAllocZ
+ */
+DECLINLINE(void *) PDMDevHlpMMHeapAllocZ(PPDMDEVINS pDevIns, size_t cb)
+{
+ return pDevIns->pHlpR3->pfnMMHeapAllocZ(pDevIns, cb);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMMHeapFree
+ */
+DECLINLINE(void) PDMDevHlpMMHeapFree(PPDMDEVINS pDevIns, void *pv)
+{
+ pDevIns->pHlpR3->pfnMMHeapFree(pDevIns, pv);
+}
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMState
+ */
+DECLINLINE(VMSTATE) PDMDevHlpVMState(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnVMState(pDevIns);
+}
+
+#ifdef IN_RING3
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMTeleportedAndNotFullyResumedYet
+ */
+DECLINLINE(bool) PDMDevHlpVMTeleportedAndNotFullyResumedYet(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnVMTeleportedAndNotFullyResumedYet(pDevIns);
+}
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMSetError
+ */
+DECLINLINE(int) PDMDevHlpVMSetError(PPDMDEVINS pDevIns, const int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
+{
+ va_list va;
+ va_start(va, pszFormat);
+ pDevIns->CTX_SUFF(pHlp)->pfnVMSetErrorV(pDevIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
+ va_end(va);
+ return rc;
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMSetRuntimeError
+ */
+DECLINLINE(int) PDMDevHlpVMSetRuntimeError(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
+{
+ va_list va;
+ int rc;
+ va_start(va, pszFormat);
+ rc = pDevIns->CTX_SUFF(pHlp)->pfnVMSetRuntimeErrorV(pDevIns, fFlags, pszErrorId, pszFormat, va);
+ va_end(va);
+ return rc;
+}
+
+/**
+ * VBOX_STRICT wrapper for pHlp->pfnDBGFStopV.
+ *
+ * @returns VBox status code which must be passed up to the VMM. This will be
+ * VINF_SUCCESS in non-strict builds.
+ * @param pDevIns The device instance.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Message. (optional)
+ * @param ... Message parameters.
+ */
+DECLINLINE(int) PDMDevHlpDBGFStop(PPDMDEVINS pDevIns, RT_SRC_POS_DECL, const char *pszFormat, ...)
+{
+#ifdef VBOX_STRICT
+# ifdef IN_RING3
+ int rc;
+ va_list args;
+ va_start(args, pszFormat);
+ rc = pDevIns->pHlpR3->pfnDBGFStopV(pDevIns, RT_SRC_POS_ARGS, pszFormat, args);
+ va_end(args);
+ return rc;
+# else
+ NOREF(pDevIns);
+ NOREF(pszFile);
+ NOREF(iLine);
+ NOREF(pszFunction);
+ NOREF(pszFormat);
+ return VINF_EM_DBG_STOP;
+# endif
+#else
+ NOREF(pDevIns);
+ NOREF(pszFile);
+ NOREF(iLine);
+ NOREF(pszFunction);
+ NOREF(pszFormat);
+ return VINF_SUCCESS;
+#endif
+}
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDBGFInfoRegister
+ */
+DECLINLINE(int) PDMDevHlpDBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler)
+{
+ return pDevIns->pHlpR3->pfnDBGFInfoRegister(pDevIns, pszName, pszDesc, pfnHandler);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSTAMRegister
+ */
+DECLINLINE(void) PDMDevHlpSTAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
+{
+ pDevIns->pHlpR3->pfnSTAMRegister(pDevIns, pvSample, enmType, pszName, enmUnit, pszDesc);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSTAMRegisterF
+ */
+DECLINLINE(void) PDMDevHlpSTAMRegisterF(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ const char *pszDesc, const char *pszName, ...)
+{
+ va_list va;
+ va_start(va, pszName);
+ pDevIns->pHlpR3->pfnSTAMRegisterV(pDevIns, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, va);
+ va_end(va);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCIRegister
+ */
+DECLINLINE(int) PDMDevHlpPCIRegister(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev)
+{
+ return pDevIns->pHlpR3->pfnPCIRegister(pDevIns, pPciDev);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCIIORegionRegister
+ */
+DECLINLINE(int) PDMDevHlpPCIIORegionRegister(PPDMDEVINS pDevIns, int iRegion, uint32_t cbRegion, PCIADDRESSSPACE enmType, PFNPCIIOREGIONMAP pfnCallback)
+{
+ return pDevIns->pHlpR3->pfnPCIIORegionRegister(pDevIns, iRegion, cbRegion, enmType, pfnCallback);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCIRegisterMsi
+ */
+DECLINLINE(int) PDMDevHlpPCIRegisterMsi(PPDMDEVINS pDevIns, PPDMMSIREG pMsiReg)
+{
+ return pDevIns->pHlpR3->pfnPCIRegisterMsi(pDevIns, pMsiReg);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCISetConfigCallbacks
+ */
+DECLINLINE(void) PDMDevHlpPCISetConfigCallbacks(PPDMDEVINS pDevIns, PPCIDEVICE pPciDev, PFNPCICONFIGREAD pfnRead, PPFNPCICONFIGREAD ppfnReadOld,
+ PFNPCICONFIGWRITE pfnWrite, PPFNPCICONFIGWRITE ppfnWriteOld)
+{
+ pDevIns->pHlpR3->pfnPCISetConfigCallbacks(pDevIns, pPciDev, pfnRead, ppfnReadOld, pfnWrite, ppfnWriteOld);
+}
+
+/**
+ * Reads data via bus mastering, if enabled. If no bus mastering is available,
+ * this function does nothing and returns VINF_PGM_PCI_PHYS_READ_BM_DISABLED.
+ *
+ * @return IPRT status code.
+ */
+DECLINLINE(int) PDMDevHlpPCIDevPhysRead(PPCIDEVICE pPciDev, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead)
+{
+ AssertPtrReturn(pPciDev, VERR_INVALID_POINTER);
+ AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
+ AssertReturn(cbRead, VERR_INVALID_PARAMETER);
+
+ if (!PCIDevIsBusmaster(pPciDev))
+ {
+#ifdef DEBUG
+ Log2(("%s: %RU16:%RU16: No bus master (anymore), skipping read %p (%z)\n", __FUNCTION__,
+ PCIDevGetVendorId(pPciDev), PCIDevGetDeviceId(pPciDev), pvBuf, cbRead));
+#endif
+ return VINF_PDM_PCI_PHYS_READ_BM_DISABLED;
+ }
+
+ return PDMDevHlpPhysRead(pPciDev->pDevIns, GCPhys, pvBuf, cbRead);
+}
+
+/**
+ * Writes data via bus mastering, if enabled. If no bus mastering is available,
+ * this function does nothing and returns VINF_PGM_PCI_PHYS_WRITE_BM_DISABLED.
+ *
+ * @return IPRT status code.
+ */
+DECLINLINE(int) PDMDevHlpPCIDevPhysWrite(PPCIDEVICE pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite)
+{
+ AssertPtrReturn(pPciDev, VERR_INVALID_POINTER);
+ AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
+ AssertReturn(cbWrite, VERR_INVALID_PARAMETER);
+
+ if (!PCIDevIsBusmaster(pPciDev))
+ {
+#ifdef DEBUG
+ Log2(("%s: %RU16:%RU16: No bus master (anymore), skipping write %p (%z)\n", __FUNCTION__,
+ PCIDevGetVendorId(pPciDev), PCIDevGetDeviceId(pPciDev), pvBuf, cbWrite));
+#endif
+ return VINF_PDM_PCI_PHYS_WRITE_BM_DISABLED;
+ }
+
+ return PDMDevHlpPhysWrite(pPciDev->pDevIns, GCPhys, pvBuf, cbWrite);
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCISetIrq
+ */
+DECLINLINE(void) PDMDevHlpPCISetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnPCISetIrq(pDevIns, iIrq, iLevel);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCISetIrqNoWait
+ */
+DECLINLINE(void) PDMDevHlpPCISetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnPCISetIrq(pDevIns, iIrq, iLevel);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnISASetIrq
+ */
+DECLINLINE(void) PDMDevHlpISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnISASetIrq(pDevIns, iIrq, iLevel);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnISASetIrqNoWait
+ */
+DECLINLINE(void) PDMDevHlpISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
+{
+ pDevIns->CTX_SUFF(pHlp)->pfnISASetIrq(pDevIns, iIrq, iLevel);
+}
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDriverAttach
+ */
+DECLINLINE(int) PDMDevHlpDriverAttach(PPDMDEVINS pDevIns, uint32_t iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
+{
+ return pDevIns->pHlpR3->pfnDriverAttach(pDevIns, iLun, pBaseInterface, ppBaseInterface, pszDesc);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnQueueCreate
+ */
+DECLINLINE(int) PDMDevHlpQueueCreate(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName, PPDMQUEUE *ppQueue)
+{
+ return pDevIns->pHlpR3->pfnQueueCreate(pDevIns, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, ppQueue);
+}
+
+/**
+ * Initializes a PDM critical section.
+ *
+ * The PDM critical sections are derived from the IPRT critical sections, but
+ * works in RC and R0 as well.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pCritSect Pointer to the critical section.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszNameFmt Format string for naming the critical section.
+ * For statistics and lock validation.
+ * @param ... Arguments for the format string.
+ */
+DECLINLINE(int) PDMDevHlpCritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL, const char *pszNameFmt, ...)
+{
+ int rc;
+ va_list va;
+ va_start(va, pszNameFmt);
+ rc = pDevIns->pHlpR3->pfnCritSectInit(pDevIns, pCritSect, RT_SRC_POS_ARGS, pszNameFmt, va);
+ va_end(va);
+ return rc;
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnCritSectGetNop
+ */
+DECLINLINE(PPDMCRITSECT) PDMDevHlpCritSectGetNop(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnCritSectGetNop(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnCritSectGetNopR0
+ */
+DECLINLINE(R0PTRTYPE(PPDMCRITSECT)) PDMDevHlpCritSectGetNopR0(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnCritSectGetNopR0(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnCritSectGetNopRC
+ */
+DECLINLINE(RCPTRTYPE(PPDMCRITSECT)) PDMDevHlpCritSectGetNopRC(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnCritSectGetNopRC(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSetDeviceCritSect
+ */
+DECLINLINE(int) PDMDevHlpSetDeviceCritSect(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
+{
+ return pDevIns->pHlpR3->pfnSetDeviceCritSect(pDevIns, pCritSect);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnThreadCreate
+ */
+DECLINLINE(int) PDMDevHlpThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
+ PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
+{
+ return pDevIns->pHlpR3->pfnThreadCreate(pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnSetAsyncNotification
+ */
+DECLINLINE(int) PDMDevHlpSetAsyncNotification(PPDMDEVINS pDevIns, PFNPDMDEVASYNCNOTIFY pfnAsyncNotify)
+{
+ return pDevIns->pHlpR3->pfnSetAsyncNotification(pDevIns, pfnAsyncNotify);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnAsyncNotificationCompleted
+ */
+DECLINLINE(void) PDMDevHlpAsyncNotificationCompleted(PPDMDEVINS pDevIns)
+{
+ pDevIns->pHlpR3->pfnAsyncNotificationCompleted(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnA20Set
+ */
+DECLINLINE(void) PDMDevHlpA20Set(PPDMDEVINS pDevIns, bool fEnable)
+{
+ pDevIns->pHlpR3->pfnA20Set(pDevIns, fEnable);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnRTCRegister
+ */
+DECLINLINE(int) PDMDevHlpRTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
+{
+ return pDevIns->pHlpR3->pfnRTCRegister(pDevIns, pRtcReg, ppRtcHlp);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPCIBusRegister
+ */
+DECLINLINE(int) PDMDevHlpPCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREG pPciBusReg, PCPDMPCIHLPR3 *ppPciHlpR3)
+{
+ return pDevIns->pHlpR3->pfnPCIBusRegister(pDevIns, pPciBusReg, ppPciHlpR3);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPICRegister
+ */
+DECLINLINE(int) PDMDevHlpPICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLPR3 *ppPicHlpR3)
+{
+ return pDevIns->pHlpR3->pfnPICRegister(pDevIns, pPicReg, ppPicHlpR3);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnAPICRegister
+ */
+DECLINLINE(int) PDMDevHlpAPICRegister(PPDMDEVINS pDevIns, PPDMAPICREG pApicReg, PCPDMAPICHLPR3 *ppApicHlpR3)
+{
+ return pDevIns->pHlpR3->pfnAPICRegister(pDevIns, pApicReg, ppApicHlpR3);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfn
+ */
+DECLINLINE(int) PDMDevHlpIOAPICRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLPR3 *ppIoApicHlpR3)
+{
+ return pDevIns->pHlpR3->pfnIOAPICRegister(pDevIns, pIoApicReg, ppIoApicHlpR3);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnHPETRegister
+ */
+DECLINLINE(int) PDMDevHlpHPETRegister(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR3 *ppHpetHlpR3)
+{
+ return pDevIns->pHlpR3->pfnHPETRegister(pDevIns, pHpetReg, ppHpetHlpR3);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnPciRawRegister
+ */
+DECLINLINE(int) PDMDevHlpPciRawRegister(PPDMDEVINS pDevIns, PPDMPCIRAWREG pPciRawReg, PCPDMPCIRAWHLPR3 *ppPciRawHlpR3)
+{
+ return pDevIns->pHlpR3->pfnPciRawRegister(pDevIns, pPciRawReg, ppPciRawHlpR3);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDMACRegister
+ */
+DECLINLINE(int) PDMDevHlpDMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
+{
+ return pDevIns->pHlpR3->pfnDMACRegister(pDevIns, pDmacReg, ppDmacHlp);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDMARegister
+ */
+DECLINLINE(int) PDMDevHlpDMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
+{
+ return pDevIns->pHlpR3->pfnDMARegister(pDevIns, uChannel, pfnTransferHandler, pvUser);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDMAReadMemory
+ */
+DECLINLINE(int) PDMDevHlpDMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
+{
+ return pDevIns->pHlpR3->pfnDMAReadMemory(pDevIns, uChannel, pvBuffer, off, cbBlock, pcbRead);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDMAWriteMemory
+ */
+DECLINLINE(int) PDMDevHlpDMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
+{
+ return pDevIns->pHlpR3->pfnDMAWriteMemory(pDevIns, uChannel, pvBuffer, off, cbBlock, pcbWritten);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDMASetDREQ
+ */
+DECLINLINE(int) PDMDevHlpDMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
+{
+ return pDevIns->pHlpR3->pfnDMASetDREQ(pDevIns, uChannel, uLevel);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDMAGetChannelMode
+ */
+DECLINLINE(uint8_t) PDMDevHlpDMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
+{
+ return pDevIns->pHlpR3->pfnDMAGetChannelMode(pDevIns, uChannel);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnDMASchedule
+ */
+DECLINLINE(void) PDMDevHlpDMASchedule(PPDMDEVINS pDevIns)
+{
+ pDevIns->pHlpR3->pfnDMASchedule(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnCMOSWrite
+ */
+DECLINLINE(int) PDMDevHlpCMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
+{
+ return pDevIns->pHlpR3->pfnCMOSWrite(pDevIns, iReg, u8Value);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnCMOSRead
+ */
+DECLINLINE(int) PDMDevHlpCMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
+{
+ return pDevIns->pHlpR3->pfnCMOSRead(pDevIns, iReg, pu8Value);
+}
+
+/**
+ * @copydoc PDMDEVHLP::pfnCallR0
+ */
+DECLINLINE(int) PDMDevHlpCallR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg)
+{
+ return pDevIns->pHlpR3->pfnCallR0(pDevIns, uOperation, u64Arg);
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnGetVM
+ */
+DECLINLINE(PVM) PDMDevHlpGetVM(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnGetVM(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnGetVMCPU
+ */
+DECLINLINE(PVMCPU) PDMDevHlpGetVMCPU(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnGetVMCPU(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTMTimeVirtGet
+ */
+DECLINLINE(uint64_t) PDMDevHlpTMTimeVirtGet(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTMTimeVirtGet(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTMTimeVirtGetFreq
+ */
+DECLINLINE(uint64_t) PDMDevHlpTMTimeVirtGetFreq(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTMTimeVirtGetFreq(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnTMTimeVirtGetFreq
+ */
+DECLINLINE(uint64_t) PDMDevHlpTMTimeVirtGetNano(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnTMTimeVirtGetNano(pDevIns);
+}
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
+ */
+DECLINLINE(int) PDMDevHlpRegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbSize)
+{
+ return pDevIns->pHlpR3->pfnRegisterVMMDevHeap(pDevIns, GCPhys, pvHeap, cbSize);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnUnregisterVMMDevHeap
+ */
+DECLINLINE(int) PDMDevHlpUnregisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
+{
+ return pDevIns->pHlpR3->pfnUnregisterVMMDevHeap(pDevIns, GCPhys);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMReset
+ */
+DECLINLINE(int) PDMDevHlpVMReset(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnVMReset(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMSuspend
+ */
+DECLINLINE(int) PDMDevHlpVMSuspend(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnVMSuspend(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMSuspendSaveAndPowerOff
+ */
+DECLINLINE(int) PDMDevHlpVMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnVMSuspendSaveAndPowerOff(pDevIns);
+}
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnVMPowerOff
+ */
+DECLINLINE(int) PDMDevHlpVMPowerOff(PPDMDEVINS pDevIns)
+{
+ return pDevIns->pHlpR3->pfnVMPowerOff(pDevIns);
+}
+
+#endif /* IN_RING3 */
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnA20IsEnabled
+ */
+DECLINLINE(bool) PDMDevHlpA20IsEnabled(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnA20IsEnabled(pDevIns);
+}
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnGetCpuId
+ */
+DECLINLINE(void) PDMDevHlpGetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf, uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
+{
+ pDevIns->pHlpR3->pfnGetCpuId(pDevIns, iLeaf, pEax, pEbx, pEcx, pEdx);
+}
+
+#endif /* IN_RING3 */
+#ifdef IN_RING0
+
+/**
+ * @copydoc PDMDEVHLPR0::pfnCanEmulateIoBlock
+ */
+DECLINLINE(bool) PDMDevHlpCanEmulateIoBlock(PPDMDEVINS pDevIns)
+{
+ return pDevIns->CTX_SUFF(pHlp)->pfnCanEmulateIoBlock(pDevIns);
+}
+
+#endif /* IN_RING0 */
+
+
+
+
+/** Pointer to callbacks provided to the VBoxDeviceRegister() call. */
+typedef struct PDMDEVREGCB *PPDMDEVREGCB;
+
+/**
+ * Callbacks for VBoxDeviceRegister().
+ */
+typedef struct PDMDEVREGCB
+{
+ /** Interface version.
+ * This is set to PDM_DEVREG_CB_VERSION. */
+ uint32_t u32Version;
+
+ /**
+ * Registers a device with the current VM instance.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param pReg Pointer to the device registration record.
+ * This data must be permanent and readonly.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegister,(PPDMDEVREGCB pCallbacks, PCPDMDEVREG pReg));
+} PDMDEVREGCB;
+
+/** Current version of the PDMDEVREGCB structure. */
+#define PDM_DEVREG_CB_VERSION PDM_VERSION_MAKE(0xffe3, 1, 0)
+
+
+/**
+ * The VBoxDevicesRegister callback function.
+ *
+ * PDM will invoke this function after loading a device module and letting
+ * the module decide which devices to register and how to handle conflicts.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param u32Version VBox version number.
+ */
+typedef DECLCALLBACK(int) FNPDMVBOXDEVICESREGISTER(PPDMDEVREGCB pCallbacks, uint32_t u32Version);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
diff --git a/include/VBox/vmm/pdmdrv.h b/include/VBox/vmm/pdmdrv.h
new file mode 100644
index 00000000..d830ea69
--- /dev/null
+++ b/include/VBox/vmm/pdmdrv.h
@@ -0,0 +1,1829 @@
+/** @file
+ * PDM - Pluggable Device Manager, Drivers.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmdrv_h
+#define ___VBox_vmm_pdmdrv_h
+
+#include <VBox/vmm/pdmqueue.h>
+#include <VBox/vmm/pdmcritsect.h>
+#include <VBox/vmm/pdmthread.h>
+#include <VBox/vmm/pdmifs.h>
+#include <VBox/vmm/pdmins.h>
+#include <VBox/vmm/pdmcommon.h>
+#include <VBox/vmm/pdmasynccompletion.h>
+#ifdef VBOX_WITH_NETSHAPER
+#include <VBox/vmm/pdmnetshaper.h>
+#endif /* VBOX_WITH_NETSHAPER */
+#include <VBox/vmm/pdmblkcache.h>
+#include <VBox/vmm/tm.h>
+#include <VBox/vmm/ssm.h>
+#include <VBox/vmm/cfgm.h>
+#include <VBox/vmm/dbgf.h>
+#include <VBox/vmm/mm.h>
+#include <VBox/vmm/ftm.h>
+#include <VBox/err.h>
+#include <iprt/stdarg.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_driver The PDM Drivers API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/** Pointer const PDM Driver API, ring-3. */
+typedef R3PTRTYPE(struct PDMDRVHLPR3 const *) PCPDMDRVHLPR3;
+/** Pointer const PDM Driver API, ring-0. */
+typedef R0PTRTYPE(struct PDMDRVHLPR0 const *) PCPDMDRVHLPR0;
+/** Pointer const PDM Driver API, raw-mode context. */
+typedef RCPTRTYPE(struct PDMDRVHLPRC const *) PCPDMDRVHLPRC;
+
+
+/**
+ * Construct a driver instance for a VM.
+ *
+ * @returns VBox status.
+ * @param pDrvIns The driver instance data. If the registration structure
+ * is needed, it can be accessed thru pDrvIns->pReg.
+ * @param pCfg Configuration node handle for the driver. This is
+ * expected to be in high demand in the constructor and is
+ * therefore passed as an argument. When using it at other
+ * times, it can be accessed via pDrvIns->pCfg.
+ * @param fFlags Flags, combination of the PDM_TACH_FLAGS_* \#defines.
+ */
+typedef DECLCALLBACK(int) FNPDMDRVCONSTRUCT(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags);
+/** Pointer to a FNPDMDRVCONSTRUCT() function. */
+typedef FNPDMDRVCONSTRUCT *PFNPDMDRVCONSTRUCT;
+
+/**
+ * Destruct a driver instance.
+ *
+ * Most VM resources are freed by the VM. This callback is provided so that
+ * any non-VM resources can be freed correctly.
+ *
+ * @param pDrvIns The driver instance data.
+ */
+typedef DECLCALLBACK(void) FNPDMDRVDESTRUCT(PPDMDRVINS pDrvIns);
+/** Pointer to a FNPDMDRVDESTRUCT() function. */
+typedef FNPDMDRVDESTRUCT *PFNPDMDRVDESTRUCT;
+
+/**
+ * Driver relocation callback.
+ *
+ * This is called when the instance data has been relocated in raw-mode context
+ * (RC). It is also called when the RC hypervisor selects changes. The driver
+ * must fixup all necessary pointers and re-query all interfaces to other RC
+ * devices and drivers.
+ *
+ * Before the RC code is executed the first time, this function will be called
+ * with a 0 delta so RC pointer calculations can be one in one place.
+ *
+ * @param pDrvIns Pointer to the driver instance.
+ * @param offDelta The relocation delta relative to the old location.
+ *
+ * @remark A relocation CANNOT fail.
+ */
+typedef DECLCALLBACK(void) FNPDMDRVRELOCATE(PPDMDRVINS pDrvIns, RTGCINTPTR offDelta);
+/** Pointer to a FNPDMDRVRELOCATE() function. */
+typedef FNPDMDRVRELOCATE *PFNPDMDRVRELOCATE;
+
+/**
+ * Driver I/O Control interface.
+ *
+ * This is used by external components, such as the COM interface, to
+ * communicate with a driver using a driver specific interface. Generally,
+ * the driver interfaces are used for this task.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Pointer to the driver instance.
+ * @param uFunction Function to perform.
+ * @param pvIn Pointer to input data.
+ * @param cbIn Size of input data.
+ * @param pvOut Pointer to output data.
+ * @param cbOut Size of output data.
+ * @param pcbOut Where to store the actual size of the output data.
+ */
+typedef DECLCALLBACK(int) FNPDMDRVIOCTL(PPDMDRVINS pDrvIns, uint32_t uFunction,
+ void *pvIn, uint32_t cbIn,
+ void *pvOut, uint32_t cbOut, uint32_t *pcbOut);
+/** Pointer to a FNPDMDRVIOCTL() function. */
+typedef FNPDMDRVIOCTL *PFNPDMDRVIOCTL;
+
+/**
+ * Power On notification.
+ *
+ * @param pDrvIns The driver instance data.
+ */
+typedef DECLCALLBACK(void) FNPDMDRVPOWERON(PPDMDRVINS pDrvIns);
+/** Pointer to a FNPDMDRVPOWERON() function. */
+typedef FNPDMDRVPOWERON *PFNPDMDRVPOWERON;
+
+/**
+ * Reset notification.
+ *
+ * @returns VBox status.
+ * @param pDrvIns The driver instance data.
+ */
+typedef DECLCALLBACK(void) FNPDMDRVRESET(PPDMDRVINS pDrvIns);
+/** Pointer to a FNPDMDRVRESET() function. */
+typedef FNPDMDRVRESET *PFNPDMDRVRESET;
+
+/**
+ * Suspend notification.
+ *
+ * @returns VBox status.
+ * @param pDrvIns The driver instance data.
+ */
+typedef DECLCALLBACK(void) FNPDMDRVSUSPEND(PPDMDRVINS pDrvIns);
+/** Pointer to a FNPDMDRVSUSPEND() function. */
+typedef FNPDMDRVSUSPEND *PFNPDMDRVSUSPEND;
+
+/**
+ * Resume notification.
+ *
+ * @returns VBox status.
+ * @param pDrvIns The driver instance data.
+ */
+typedef DECLCALLBACK(void) FNPDMDRVRESUME(PPDMDRVINS pDrvIns);
+/** Pointer to a FNPDMDRVRESUME() function. */
+typedef FNPDMDRVRESUME *PFNPDMDRVRESUME;
+
+/**
+ * Power Off notification.
+ *
+ * This is only called when the VMR3PowerOff call is made on a running VM. This
+ * means that there is no notification if the VM was suspended before being
+ * powered of. There will also be no callback when hot plugging devices or when
+ * replumbing the driver stack.
+ *
+ * @param pDrvIns The driver instance data.
+ */
+typedef DECLCALLBACK(void) FNPDMDRVPOWEROFF(PPDMDRVINS pDrvIns);
+/** Pointer to a FNPDMDRVPOWEROFF() function. */
+typedef FNPDMDRVPOWEROFF *PFNPDMDRVPOWEROFF;
+
+/**
+ * Attach command.
+ *
+ * This is called to let the drive attach to a driver at runtime. This is not
+ * called during VM construction, the driver constructor have to do this by
+ * calling PDMDrvHlpAttach.
+ *
+ * This is like plugging in the keyboard or mouse after turning on the PC.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param fFlags Flags, combination of the PDM_TACH_FLAGS_* \#defines.
+ */
+typedef DECLCALLBACK(int) FNPDMDRVATTACH(PPDMDRVINS pDrvIns, uint32_t fFlags);
+/** Pointer to a FNPDMDRVATTACH() function. */
+typedef FNPDMDRVATTACH *PFNPDMDRVATTACH;
+
+/**
+ * Detach notification.
+ *
+ * This is called when a driver below it in the chain is detaching itself
+ * from it. The driver should adjust it's state to reflect this.
+ *
+ * This is like ejecting a cdrom or floppy.
+ *
+ * @param pDrvIns The driver instance.
+ * @param fFlags PDM_TACH_FLAGS_NOT_HOT_PLUG or 0.
+ */
+typedef DECLCALLBACK(void) FNPDMDRVDETACH(PPDMDRVINS pDrvIns, uint32_t fFlags);
+/** Pointer to a FNPDMDRVDETACH() function. */
+typedef FNPDMDRVDETACH *PFNPDMDRVDETACH;
+
+
+
+/**
+ * PDM Driver Registration Structure.
+ *
+ * This structure is used when registering a driver from VBoxInitDrivers() (in
+ * host ring-3 context). PDM will continue use till the VM is terminated.
+ */
+typedef struct PDMDRVREG
+{
+ /** Structure version. PDM_DRVREG_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Driver name. */
+ char szName[32];
+ /** Name of the raw-mode context module (no path).
+ * Only evalutated if PDM_DRVREG_FLAGS_RC is set. */
+ char szRCMod[32];
+ /** Name of the ring-0 module (no path).
+ * Only evalutated if PDM_DRVREG_FLAGS_R0 is set. */
+ char szR0Mod[32];
+ /** The description of the driver. The UTF-8 string pointed to shall, like this structure,
+ * remain unchanged from registration till VM destruction. */
+ const char *pszDescription;
+
+ /** Flags, combination of the PDM_DRVREG_FLAGS_* \#defines. */
+ uint32_t fFlags;
+ /** Driver class(es), combination of the PDM_DRVREG_CLASS_* \#defines. */
+ uint32_t fClass;
+ /** Maximum number of instances (per VM). */
+ uint32_t cMaxInstances;
+ /** Size of the instance data. */
+ uint32_t cbInstance;
+
+ /** Construct instance - required. */
+ PFNPDMDRVCONSTRUCT pfnConstruct;
+ /** Destruct instance - optional. */
+ PFNPDMDRVDESTRUCT pfnDestruct;
+ /** Relocation command - optional. */
+ PFNPDMDRVRELOCATE pfnRelocate;
+ /** I/O control - optional. */
+ PFNPDMDRVIOCTL pfnIOCtl;
+ /** Power on notification - optional. */
+ PFNPDMDRVPOWERON pfnPowerOn;
+ /** Reset notification - optional. */
+ PFNPDMDRVRESET pfnReset;
+ /** Suspend notification - optional. */
+ PFNPDMDRVSUSPEND pfnSuspend;
+ /** Resume notification - optional. */
+ PFNPDMDRVRESUME pfnResume;
+ /** Attach command - optional. */
+ PFNPDMDRVATTACH pfnAttach;
+ /** Detach notification - optional. */
+ PFNPDMDRVDETACH pfnDetach;
+ /** Power off notification - optional. */
+ PFNPDMDRVPOWEROFF pfnPowerOff;
+ /** @todo */
+ PFNRT pfnSoftReset;
+ /** Initialization safty marker. */
+ uint32_t u32VersionEnd;
+} PDMDRVREG;
+/** Pointer to a PDM Driver Structure. */
+typedef PDMDRVREG *PPDMDRVREG;
+/** Const pointer to a PDM Driver Structure. */
+typedef PDMDRVREG const *PCPDMDRVREG;
+
+/** Current DRVREG version number. */
+#define PDM_DRVREG_VERSION PDM_VERSION_MAKE(0xf0ff, 1, 0)
+
+/** PDM Driver Flags.
+ * @{ */
+/** @def PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT
+ * The bit count for the current host. */
+#if HC_ARCH_BITS == 32
+# define PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT UINT32_C(0x00000001)
+#elif HC_ARCH_BITS == 64
+# define PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT UINT32_C(0x00000002)
+#else
+# error Unsupported HC_ARCH_BITS value.
+#endif
+/** The host bit count mask. */
+#define PDM_DRVREG_FLAGS_HOST_BITS_MASK UINT32_C(0x00000003)
+/** This flag is used to indicate that the driver has a RC component. */
+#define PDM_DRVREG_FLAGS_RC UINT32_C(0x00000010)
+/** This flag is used to indicate that the driver has a R0 component. */
+#define PDM_DRVREG_FLAGS_R0 UINT32_C(0x00000020)
+
+/** @} */
+
+
+/** PDM Driver Classes.
+ * @{ */
+/** Mouse input driver. */
+#define PDM_DRVREG_CLASS_MOUSE RT_BIT(0)
+/** Keyboard input driver. */
+#define PDM_DRVREG_CLASS_KEYBOARD RT_BIT(1)
+/** Display driver. */
+#define PDM_DRVREG_CLASS_DISPLAY RT_BIT(2)
+/** Network transport driver. */
+#define PDM_DRVREG_CLASS_NETWORK RT_BIT(3)
+/** Block driver. */
+#define PDM_DRVREG_CLASS_BLOCK RT_BIT(4)
+/** Media driver. */
+#define PDM_DRVREG_CLASS_MEDIA RT_BIT(5)
+/** Mountable driver. */
+#define PDM_DRVREG_CLASS_MOUNTABLE RT_BIT(6)
+/** Audio driver. */
+#define PDM_DRVREG_CLASS_AUDIO RT_BIT(7)
+/** VMMDev driver. */
+#define PDM_DRVREG_CLASS_VMMDEV RT_BIT(8)
+/** Status driver. */
+#define PDM_DRVREG_CLASS_STATUS RT_BIT(9)
+/** ACPI driver. */
+#define PDM_DRVREG_CLASS_ACPI RT_BIT(10)
+/** USB related driver. */
+#define PDM_DRVREG_CLASS_USB RT_BIT(11)
+/** ISCSI Transport related driver. */
+#define PDM_DRVREG_CLASS_ISCSITRANSPORT RT_BIT(12)
+/** Char driver. */
+#define PDM_DRVREG_CLASS_CHAR RT_BIT(13)
+/** Stream driver. */
+#define PDM_DRVREG_CLASS_STREAM RT_BIT(14)
+/** SCSI driver. */
+#define PDM_DRVREG_CLASS_SCSI RT_BIT(15)
+/** Generic raw PCI device driver. */
+#define PDM_DRVREG_CLASS_PCIRAW RT_BIT(16)
+/** @} */
+
+
+/**
+ * PDM Driver Instance.
+ *
+ * @implements PDMIBASE
+ */
+typedef struct PDMDRVINS
+{
+ /** Structure version. PDM_DRVINS_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Driver instance number. */
+ uint32_t iInstance;
+
+ /** Pointer the PDM Driver API. */
+ RCPTRTYPE(PCPDMDRVHLPRC) pHlpRC;
+ /** Pointer to driver instance data. */
+ RCPTRTYPE(void *) pvInstanceDataRC;
+
+ /** Pointer the PDM Driver API. */
+ R0PTRTYPE(PCPDMDRVHLPR0) pHlpR0;
+ /** Pointer to driver instance data. */
+ R0PTRTYPE(void *) pvInstanceDataR0;
+
+ /** Pointer the PDM Driver API. */
+ R3PTRTYPE(PCPDMDRVHLPR3) pHlpR3;
+ /** Pointer to driver instance data. */
+ R3PTRTYPE(void *) pvInstanceDataR3;
+
+ /** Pointer to driver registration structure. */
+ R3PTRTYPE(PCPDMDRVREG) pReg;
+ /** Configuration handle. */
+ R3PTRTYPE(PCFGMNODE) pCfg;
+
+ /** Pointer to the base interface of the device/driver instance above. */
+ R3PTRTYPE(PPDMIBASE) pUpBase;
+ /** Pointer to the base interface of the driver instance below. */
+ R3PTRTYPE(PPDMIBASE) pDownBase;
+
+ /** The base interface of the driver.
+ * The driver constructor initializes this. */
+ PDMIBASE IBase;
+
+ /** Tracing indicator. */
+ uint32_t fTracing;
+ /** The tracing ID of this device. */
+ uint32_t idTracing;
+#if HC_ARCH_BITS == 32
+ /** Align the internal data more naturally. */
+ uint32_t au32Padding[HC_ARCH_BITS == 32 ? 7 : 0];
+#endif
+
+ /** Internal data. */
+ union
+ {
+#ifdef PDMDRVINSINT_DECLARED
+ PDMDRVINSINT s;
+#endif
+ uint8_t padding[HC_ARCH_BITS == 32 ? 40 + 32 : 72 + 24];
+ } Internal;
+
+ /** Driver instance data. The size of this area is defined
+ * in the PDMDRVREG::cbInstanceData field. */
+ char achInstanceData[4];
+} PDMDRVINS;
+
+/** Current DRVREG version number. */
+#define PDM_DRVINS_VERSION PDM_VERSION_MAKE(0xf0fe, 2, 0)
+
+/** Converts a pointer to the PDMDRVINS::IBase to a pointer to PDMDRVINS. */
+#define PDMIBASE_2_PDMDRV(pInterface) ( (PPDMDRVINS)((char *)(pInterface) - RT_OFFSETOF(PDMDRVINS, IBase)) )
+
+/** @def PDMDRVINS_2_RCPTR
+ * Converts a PDM Driver instance pointer a RC PDM Driver instance pointer.
+ */
+#define PDMDRVINS_2_RCPTR(pDrvIns) ( (RCPTRTYPE(PPDMDRVINS))((RTGCUINTPTR)(pDrvIns)->pvInstanceDataRC - RT_OFFSETOF(PDMDRVINS, achInstanceData)) )
+
+/** @def PDMDRVINS_2_R3PTR
+ * Converts a PDM Driver instance pointer a R3 PDM Driver instance pointer.
+ */
+#define PDMDRVINS_2_R3PTR(pDrvIns) ( (R3PTRTYPE(PPDMDRVINS))((RTHCUINTPTR)(pDrvIns)->pvInstanceDataR3 - RT_OFFSETOF(PDMDRVINS, achInstanceData)) )
+
+/** @def PDMDRVINS_2_R0PTR
+ * Converts a PDM Driver instance pointer a R0 PDM Driver instance pointer.
+ */
+#define PDMDRVINS_2_R0PTR(pDrvIns) ( (R0PTRTYPE(PPDMDRVINS))((RTR0UINTPTR)(pDrvIns)->pvInstanceDataR0 - RT_OFFSETOF(PDMDRVINS, achInstanceData)) )
+
+
+
+/**
+ * Checks the structure versions of the drive instance and driver helpers,
+ * returning if they are incompatible.
+ *
+ * Intended for the constructor.
+ *
+ * @param pDrvIns Pointer to the PDM driver instance.
+ */
+#define PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns) \
+ do \
+ { \
+ PPDMDRVINS pDrvInsTypeCheck = (pDrvIns); NOREF(pDrvInsTypeCheck); \
+ AssertLogRelMsgReturn(PDM_VERSION_ARE_COMPATIBLE((pDrvIns)->u32Version, PDM_DRVINS_VERSION), \
+ ("DrvIns=%#x mine=%#x\n", (pDrvIns)->u32Version, PDM_DRVINS_VERSION), \
+ VERR_PDM_DRVINS_VERSION_MISMATCH); \
+ AssertLogRelMsgReturn(PDM_VERSION_ARE_COMPATIBLE((pDrvIns)->pHlpR3->u32Version, PDM_DRVHLPR3_VERSION), \
+ ("DrvHlp=%#x mine=%#x\n", (pDrvIns)->pHlpR3->u32Version, PDM_DRVHLPR3_VERSION), \
+ VERR_PDM_DRVHLPR3_VERSION_MISMATCH); \
+ } while (0)
+
+/**
+ * Quietly checks the structure versions of the drive instance and driver
+ * helpers, returning if they are incompatible.
+ *
+ * Intended for the destructor.
+ *
+ * @param pDrvIns Pointer to the PDM driver instance.
+ */
+#define PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns) \
+ do \
+ { \
+ PPDMDRVINS pDrvInsTypeCheck = (pDrvIns); NOREF(pDrvInsTypeCheck); \
+ if (RT_UNLIKELY( !PDM_VERSION_ARE_COMPATIBLE((pDrvIns)->u32Version, PDM_DRVINS_VERSION) \
+ || !PDM_VERSION_ARE_COMPATIBLE((pDrvIns)->pHlpR3->u32Version, PDM_DRVHLPR3_VERSION)) ) \
+ return; \
+ } while (0)
+
+/**
+ * Wrapper around CFGMR3ValidateConfig for the root config for use in the
+ * constructor - returns on failure.
+ *
+ * This should be invoked after having initialized the instance data
+ * sufficiently for the correct operation of the destructor. The destructor is
+ * always called!
+ *
+ * @param pDrvIns Pointer to the PDM driver instance.
+ * @param pszValidValues Patterns describing the valid value names. See
+ * RTStrSimplePatternMultiMatch for details on the
+ * pattern syntax.
+ * @param pszValidNodes Patterns describing the valid node (key) names.
+ * Pass empty string if no valid nodess.
+ */
+#define PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, pszValidValues, pszValidNodes) \
+ do \
+ { \
+ int rcValCfg = CFGMR3ValidateConfig((pDrvIns)->pCfg, "/", pszValidValues, pszValidNodes, \
+ (pDrvIns)->pReg->szName, (pDrvIns)->iInstance); \
+ if (RT_FAILURE(rcValCfg)) \
+ return rcValCfg; \
+ } while (0)
+
+
+
+/**
+ * USB hub registration structure.
+ */
+typedef struct PDMUSBHUBREG
+{
+ /** Structure version number. PDM_USBHUBREG_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Request the hub to attach of the specified device.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The hub instance.
+ * @param pUsbIns The device to attach.
+ * @param piPort Where to store the port number the device was attached to.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAttachDevice,(PPDMDRVINS pDrvIns, PPDMUSBINS pUsbIns, uint32_t *piPort));
+
+ /**
+ * Request the hub to detach of the specified device.
+ *
+ * The device has previously been attached to the hub with the
+ * pfnAttachDevice call. This call is not currently expected to
+ * fail.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The hub instance.
+ * @param pUsbIns The device to detach.
+ * @param iPort The port number returned by the attach call.
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDetachDevice,(PPDMDRVINS pDrvIns, PPDMUSBINS pUsbIns, uint32_t iPort));
+
+ /** Counterpart to u32Version, same value. */
+ uint32_t u32TheEnd;
+} PDMUSBHUBREG;
+/** Pointer to a const USB hub registration structure. */
+typedef const PDMUSBHUBREG *PCPDMUSBHUBREG;
+
+/** Current PDMUSBHUBREG version number. */
+#define PDM_USBHUBREG_VERSION PDM_VERSION_MAKE(0xf0fd, 1, 0)
+
+
+/**
+ * USB hub helpers.
+ * This is currently just a place holder.
+ */
+typedef struct PDMUSBHUBHLP
+{
+ /** Structure version. PDM_USBHUBHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMUSBHUBHLP;
+/** Pointer to PCI helpers. */
+typedef PDMUSBHUBHLP *PPDMUSBHUBHLP;
+/** Pointer to const PCI helpers. */
+typedef const PDMUSBHUBHLP *PCPDMUSBHUBHLP;
+/** Pointer to const PCI helpers pointer. */
+typedef PCPDMUSBHUBHLP *PPCPDMUSBHUBHLP;
+
+/** Current PDMUSBHUBHLP version number. */
+#define PDM_USBHUBHLP_VERSION PDM_VERSION_MAKE(0xf0fc, 1, 0)
+
+
+/**
+ * PDM Driver API - raw-mode context variant.
+ */
+typedef struct PDMDRVHLPRC
+{
+ /** Structure version. PDM_DRVHLPRC_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDrvIns Driver instance.
+ * @param rc VBox status code.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnVMSetError,(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...));
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDrvIns Driver instance.
+ * @param rc VBox status code.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnVMSetErrorV,(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnVMSetRuntimeError,(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLRCCALLBACKMEMBER(int, pfnVMSetRuntimeErrorV,(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va));
+
+ /**
+ * Assert that the current thread is the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDrvIns Driver instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLRCCALLBACKMEMBER(bool, pfnAssertEMT,(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Assert that the current thread is NOT the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDrvIns Driver instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLRCCALLBACKMEMBER(bool, pfnAssertOther,(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Notify FTM about a checkpoint occurrence
+ *
+ * @param pDrvIns The driver instance.
+ * @param enmType Checkpoint type
+ * @thread Any
+ */
+ DECLRCCALLBACKMEMBER(int, pfnFTSetCheckpoint,(PPDMDRVINS pDrvIns, FTMCHECKPOINTTYPE enmType));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMDRVHLPRC;
+/** Current PDMDRVHLPRC version number. */
+#define PDM_DRVHLPRC_VERSION PDM_VERSION_MAKE(0xf0f9, 2, 0)
+
+
+/**
+ * PDM Driver API, ring-0 context.
+ */
+typedef struct PDMDRVHLPR0
+{
+ /** Structure version. PDM_DRVHLPR0_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDrvIns Driver instance.
+ * @param rc VBox status code.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnVMSetError,(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...));
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDrvIns Driver instance.
+ * @param rc VBox status code.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnVMSetErrorV,(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnVMSetRuntimeError,(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR0CALLBACKMEMBER(int, pfnVMSetRuntimeErrorV,(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va));
+
+ /**
+ * Assert that the current thread is the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDrvIns Driver instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR0CALLBACKMEMBER(bool, pfnAssertEMT,(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Assert that the current thread is NOT the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDrvIns Driver instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR0CALLBACKMEMBER(bool, pfnAssertOther,(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Notify FTM about a checkpoint occurrence
+ *
+ * @param pDrvIns The driver instance.
+ * @param enmType Checkpoint type
+ * @thread Any
+ */
+ DECLR0CALLBACKMEMBER(int, pfnFTSetCheckpoint,(PPDMDRVINS pDrvIns, FTMCHECKPOINTTYPE enmType));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMDRVHLPR0;
+/** Current DRVHLP version number. */
+#define PDM_DRVHLPR0_VERSION PDM_VERSION_MAKE(0xf0f8, 2, 0)
+
+
+#ifdef IN_RING3
+
+/**
+ * PDM Driver API.
+ */
+typedef struct PDMDRVHLPR3
+{
+ /** Structure version. PDM_DRVHLPR3_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Attaches a driver (chain) to the driver.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param fFlags PDM_TACH_FLAGS_NOT_HOT_PLUG or 0.
+ * @param ppBaseInterface Where to store the pointer to the base interface.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAttach,(PPDMDRVINS pDrvIns, uint32_t fFlags, PPDMIBASE *ppBaseInterface));
+
+ /**
+ * Detach the driver the drivers below us.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param fFlags PDM_TACH_FLAGS_NOT_HOT_PLUG or 0.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDetach,(PPDMDRVINS pDrvIns, uint32_t fFlags));
+
+ /**
+ * Detach the driver from the driver above it and destroy this
+ * driver and all drivers below it.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param fFlags PDM_TACH_FLAGS_NOT_HOT_PLUG or 0.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDetachSelf,(PPDMDRVINS pDrvIns, uint32_t fFlags));
+
+ /**
+ * Prepare a media mount.
+ *
+ * The driver must not have anything attached to itself
+ * when calling this function as the purpose is to set up the configuration
+ * of an future attachment.
+ *
+ * @returns VBox status code
+ * @param pDrvIns Driver instance.
+ * @param pszFilename Pointer to filename. If this is NULL it assumed that the caller have
+ * constructed a configuration which can be attached to the bottom driver.
+ * @param pszCoreDriver Core driver name. NULL will cause autodetection. Ignored if pszFilanem is NULL.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMountPrepare,(PPDMDRVINS pDrvIns, const char *pszFilename, const char *pszCoreDriver));
+
+ /**
+ * Assert that the current thread is the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDrvIns Driver instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertEMT,(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Assert that the current thread is NOT the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pDrvIns Driver instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertOther,(PPDMDRVINS pDrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDrvIns Driver instance.
+ * @param rc VBox status code.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetError,(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...));
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pDrvIns Driver instance.
+ * @param rc VBox status code.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetErrorV,(PPDMDRVINS pDrvIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetRuntimeError,(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetRuntimeErrorV,(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va));
+
+ /**
+ * Gets the VM state.
+ *
+ * @returns VM state.
+ * @param pDrvIns The driver instance.
+ * @thread Any thread (just keep in mind that it's volatile info).
+ */
+ DECLR3CALLBACKMEMBER(VMSTATE, pfnVMState, (PPDMDRVINS pDrvIns));
+
+ /**
+ * Checks if the VM was teleported and hasn't been fully resumed yet.
+ *
+ * @returns true / false.
+ * @param pDrvIns The driver instance.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnVMTeleportedAndNotFullyResumedYet,(PPDMDRVINS pDrvIns));
+
+ /**
+ * Gets the support driver session.
+ *
+ * This is intended for working using the semaphore API.
+ *
+ * @returns Support driver session handle.
+ * @param pDrvIns The driver instance.
+ */
+ DECLR3CALLBACKMEMBER(PSUPDRVSESSION, pfnGetSupDrvSession,(PPDMDRVINS pDrvIns));
+
+ /**
+ * Create a queue.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param cbItem Size a queue item.
+ * @param cItems Number of items in the queue.
+ * @param cMilliesInterval Number of milliseconds between polling the queue.
+ * If 0 then the emulation thread will be notified whenever an item arrives.
+ * @param pfnCallback The consumer function.
+ * @param pszName The queue base name. The instance number will be
+ * appended automatically.
+ * @param ppQueue Where to store the queue handle on success.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueueCreate,(PPDMDRVINS pDrvIns, uint32_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEDRV pfnCallback, const char *pszName, PPDMQUEUE *ppQueue));
+
+ /**
+ * Query the virtual timer frequency.
+ *
+ * @returns Frequency in Hz.
+ * @param pDrvIns Driver instance.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTMGetVirtualFreq,(PPDMDRVINS pDrvIns));
+
+ /**
+ * Query the virtual time.
+ *
+ * @returns The current virtual time.
+ * @param pDrvIns Driver instance.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTMGetVirtualTime,(PPDMDRVINS pDrvIns));
+
+ /**
+ * Creates a timer.
+ *
+ * @returns VBox status.
+ * @param pDrvIns Driver instance.
+ * @param enmClock The clock to use on this timer.
+ * @param pfnCallback Callback function.
+ * @param pvUser The user argument to the callback.
+ * @param fFlags Timer creation flags, see grp_tm_timer_flags.
+ * @param pszDesc Pointer to description string which must stay around
+ * until the timer is fully destroyed (i.e. a bit after TMTimerDestroy()).
+ * @param ppTimer Where to store the timer on success.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTMTimerCreate,(PPDMDRVINS pDrvIns, TMCLOCK enmClock, PFNTMTIMERDRV pfnCallback, void *pvUser, uint32_t fFlags, const char *pszDesc, PPTMTIMERR3 ppTimer));
+
+ /**
+ * Register a save state data unit.
+ *
+ * @returns VBox status.
+ * @param pDrvIns Driver instance.
+ * @param uVersion Data layout version number.
+ * @param cbGuess The approximate amount of data in the unit.
+ * Only for progress indicators.
+ *
+ * @param pfnLivePrep Prepare live save callback, optional.
+ * @param pfnLiveExec Execute live save callback, optional.
+ * @param pfnLiveVote Vote live save callback, optional.
+ *
+ * @param pfnSavePrep Prepare save callback, optional.
+ * @param pfnSaveExec Execute save callback, optional.
+ * @param pfnSaveDone Done save callback, optional.
+ *
+ * @param pfnLoadPrep Prepare load callback, optional.
+ * @param pfnLoadExec Execute load callback, optional.
+ * @param pfnLoadDone Done load callback, optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSSMRegister,(PPDMDRVINS pDrvIns, uint32_t uVersion, size_t cbGuess,
+ PFNSSMDRVLIVEPREP pfnLivePrep, PFNSSMDRVLIVEEXEC pfnLiveExec, PFNSSMDRVLIVEVOTE pfnLiveVote,
+ PFNSSMDRVSAVEPREP pfnSavePrep, PFNSSMDRVSAVEEXEC pfnSaveExec, PFNSSMDRVSAVEDONE pfnSaveDone,
+ PFNSSMDRVLOADPREP pfnLoadPrep, PFNSSMDRVLOADEXEC pfnLoadExec, PFNSSMDRVLOADDONE pfnLoadDone));
+
+ /**
+ * Deregister a save state data unit.
+ *
+ * @returns VBox status.
+ * @param pDrvIns Driver instance.
+ * @param pszName Data unit name.
+ * @param uInstance The instance identifier of the data unit.
+ * This must together with the name be unique.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSSMDeregister,(PPDMDRVINS pDrvIns, const char *pszName, uint32_t uInstance));
+
+ /**
+ * Register an info handler with DBGF.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param pszName Data unit name.
+ * @param pszDesc The description of the info and any arguments
+ * the handler may take.
+ * @param pfnHandler The handler function to be called to display the
+ * info.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFInfoRegister,(PPDMDRVINS pDrvIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDRV pfnHandler));
+
+ /**
+ * Deregister an info handler from DBGF.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance.
+ * @param pszName Data unit name.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFInfoDeregister,(PPDMDRVINS pDrvIns, const char *pszName));
+
+ /**
+ * Registers a statistics sample if statistics are enabled.
+ *
+ * @param pDrvIns Driver instance.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param pszName Sample name. The name is on this form "/<component>/<sample>".
+ * Further nesting is possible.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSTAMRegister,(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, const char *pszName,
+ STAMUNIT enmUnit, const char *pszDesc));
+
+ /**
+ * Same as pfnSTAMRegister except that the name is specified in a
+ * RTStrPrintf like fashion.
+ *
+ * @param pDrvIns Driver instance.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param enmVisibility Visibility type specifying whether unused statistics should be visible or not.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ * @param pszName The sample name format string.
+ * @param ... Arguments to the format string.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSTAMRegisterF,(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ STAMUNIT enmUnit, const char *pszDesc, const char *pszName, ...));
+
+ /**
+ * Same as pfnSTAMRegister except that the name is specified in a
+ * RTStrPrintfV like fashion.
+ *
+ * @param pDrvIns Driver instance.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param enmVisibility Visibility type specifying whether unused statistics should be visible or not.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ * @param pszName The sample name format string.
+ * @param args Arguments to the format string.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSTAMRegisterV,(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args));
+
+ /**
+ * Deregister a statistic item previously registered with pfnSTAMRegister,
+ * pfnSTAMRegisterF or pfnSTAMRegisterV
+ *
+ * @returns VBox status.
+ * @param pDrvIns Driver instance.
+ * @param pvSample Pointer to the sample.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSTAMDeregister,(PPDMDRVINS pDrvIns, void *pvSample));
+
+ /**
+ * Calls the HC R0 VMM entry point, in a safer but slower manner than
+ * SUPR3CallVMMR0.
+ *
+ * When entering using this call the R0 components can call into the host kernel
+ * (i.e. use the SUPR0 and RT APIs).
+ *
+ * See VMMR0Entry() for more details.
+ *
+ * @returns error code specific to uFunction.
+ * @param pDrvIns The driver instance.
+ * @param uOperation Operation to execute.
+ * This is limited to services.
+ * @param pvArg Pointer to argument structure or if cbArg is 0 just an value.
+ * @param cbArg The size of the argument. This is used to copy whatever the argument
+ * points at into a kernel buffer to avoid problems like the user page
+ * being invalidated while we're executing the call.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSUPCallVMMR0Ex,(PPDMDRVINS pDrvIns, unsigned uOperation, void *pvArg, unsigned cbArg));
+
+ /**
+ * Registers a USB HUB.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param fVersions Indicates the kinds of USB devices that can be attached to this HUB.
+ * @param cPorts The number of ports.
+ * @param pUsbHubReg The hub callback structure that PDMUsb uses to interact with it.
+ * @param ppUsbHubHlp The helper callback structure that the hub uses to talk to PDMUsb.
+ *
+ * @thread EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUSBRegisterHub,(PPDMDRVINS pDrvIns, uint32_t fVersions, uint32_t cPorts, PCPDMUSBHUBREG pUsbHubReg, PPCPDMUSBHUBHLP ppUsbHubHlp));
+
+ /**
+ * Set up asynchronous handling of a suspend, reset or power off notification.
+ *
+ * This shall only be called when getting the notification. It must be called
+ * for each one.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pfnAsyncNotify The callback.
+ * @thread EMT(0)
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetAsyncNotification, (PPDMDRVINS pDrvIns, PFNPDMDRVASYNCNOTIFY pfnAsyncNotify));
+
+ /**
+ * Notify EMT(0) that the driver has completed the asynchronous notification
+ * handling.
+ *
+ * This can be called at any time, spurious calls will simply be ignored.
+ *
+ * @param pDrvIns The driver instance.
+ * @thread Any
+ */
+ DECLR3CALLBACKMEMBER(void, pfnAsyncNotificationCompleted, (PPDMDRVINS pDrvIns));
+
+ /**
+ * Creates a PDM thread.
+ *
+ * This differs from the RTThreadCreate() API in that PDM takes care of suspending,
+ * resuming, and destroying the thread as the VM state changes.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param ppThread Where to store the thread 'handle'.
+ * @param pvUser The user argument to the thread function.
+ * @param pfnThread The thread function.
+ * @param pfnWakeup The wakup callback. This is called on the EMT thread when
+ * a state change is pending.
+ * @param cbStack See RTThreadCreate.
+ * @param enmType See RTThreadCreate.
+ * @param pszName See RTThreadCreate.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnThreadCreate,(PPDMDRVINS pDrvIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDRV pfnThread,
+ PFNPDMTHREADWAKEUPDRV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName));
+
+ /**
+ * Creates an async completion template for a driver instance.
+ *
+ * The template is used when creating new completion tasks.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param ppTemplate Where to store the template pointer on success.
+ * @param pfnCompleted The completion callback routine.
+ * @param pvTemplateUser Template user argument.
+ * @param pszDesc Description.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAsyncCompletionTemplateCreate,(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
+ PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser,
+ const char *pszDesc));
+
+#ifdef VBOX_WITH_NETSHAPER
+ /**
+ * Attaches network filter driver to a bandwidth group.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pcszBwGroup Name of the bandwidth group to attach to.
+ * @param pFilter Pointer to the filter we attach.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnNetShaperAttach,(PPDMDRVINS pDrvIns, const char *pszBwGroup,
+ PPDMNSFILTER pFilter));
+
+
+ /**
+ * Detaches network filter driver to a bandwidth group.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pFilter Pointer to the filter we attach.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnNetShaperDetach,(PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter));
+#endif /* VBOX_WITH_NETSHAPER */
+
+
+ /**
+ * Resolves the symbol for a raw-mode context interface.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pvInterface The interface structure.
+ * @param cbInterface The size of the interface structure.
+ * @param pszSymPrefix What to prefix the symbols in the list with before
+ * resolving them. This must start with 'drv' and
+ * contain the driver name.
+ * @param pszSymList List of symbols corresponding to the interface.
+ * There is generally a there is generally a define
+ * holding this list associated with the interface
+ * definition (INTERFACE_SYM_LIST). For more details
+ * see PDMR3LdrGetInterfaceSymbols.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLdrGetRCInterfaceSymbols,(PPDMDRVINS pDrvIns, void *pvInterface, size_t cbInterface,
+ const char *pszSymPrefix, const char *pszSymList));
+
+ /**
+ * Resolves the symbol for a ring-0 context interface.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pvInterface The interface structure.
+ * @param cbInterface The size of the interface structure.
+ * @param pszSymPrefix What to prefix the symbols in the list with before
+ * resolving them. This must start with 'drv' and
+ * contain the driver name.
+ * @param pszSymList List of symbols corresponding to the interface.
+ * There is generally a there is generally a define
+ * holding this list associated with the interface
+ * definition (INTERFACE_SYM_LIST). For more details
+ * see PDMR3LdrGetInterfaceSymbols.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLdrGetR0InterfaceSymbols,(PPDMDRVINS pDrvIns, void *pvInterface, size_t cbInterface,
+ const char *pszSymPrefix, const char *pszSymList));
+ /**
+ * Initializes a PDM critical section.
+ *
+ * The PDM critical sections are derived from the IPRT critical sections, but
+ * works in both RC and R0 as well as R3.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pCritSect Pointer to the critical section.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszName The base name of the critical section. Will be
+ * mangeled with the instance number. For
+ * statistics and lock validation.
+ * @param va Arguments for the format string.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCritSectInit,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect,
+ RT_SRC_POS_DECL, const char *pszName));
+
+ /**
+ * Call the ring-0 request handler routine of the driver.
+ *
+ * For this to work, the driver must be ring-0 enabled and export a request
+ * handler function. The name of the function must be the driver name in the
+ * PDMDRVREG struct prefixed with 'drvR0' and suffixed with 'ReqHandler'.
+ * The driver name will be capitalized. It shall take the exact same
+ * arguments as this function and be declared using PDMBOTHCBDECL. See
+ * FNPDMDRVREQHANDLERR0.
+ *
+ * @returns VBox status code.
+ * @retval VERR_SYMBOL_NOT_FOUND if the driver doesn't export the required
+ * handler function.
+ * @retval VERR_ACCESS_DENIED if the driver isn't ring-0 capable.
+ *
+ * @param pDrvIns The driver instance.
+ * @param uOperation The operation to perform.
+ * @param u64Arg 64-bit integer argument.
+ * @thread Any
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCallR0,(PPDMDRVINS pDrvIns, uint32_t uOperation, uint64_t u64Arg));
+
+ /**
+ * Notify FTM about a checkpoint occurrence
+ *
+ * @param pDrvIns The driver instance.
+ * @param enmType Checkpoint type
+ * @thread Any
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFTSetCheckpoint,(PPDMDRVINS pDrvIns, FTMCHECKPOINTTYPE enmType));
+
+ /**
+ * Creates a block cache for a driver driver instance.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param ppBlkCache Where to store the handle to the block cache.
+ * @param pfnXferComplete The I/O transfer complete callback.
+ * @param pfnXferEnqueue The I/O request enqueue callback.
+ * @param pcszId Unique ID used to identify the user.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnBlkCacheRetain, (PPDMDRVINS pDrvIns, PPPDMBLKCACHE ppBlkCache,
+ PFNPDMBLKCACHEXFERCOMPLETEDRV pfnXferComplete,
+ PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue,
+ PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard,
+ const char *pcszId));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMDRVHLPR3;
+/** Current DRVHLP version number. */
+#define PDM_DRVHLPR3_VERSION PDM_VERSION_MAKE(0xf0fb, 2, 0)
+
+#endif /* IN_RING3 */
+
+
+/**
+ * @copydoc PDMDRVHLP::pfnVMSetError
+ */
+DECLINLINE(int) PDMDrvHlpVMSetError(PPDMDRVINS pDrvIns, const int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
+{
+ va_list va;
+ va_start(va, pszFormat);
+ pDrvIns->CTX_SUFF(pHlp)->pfnVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
+ va_end(va);
+ return rc;
+}
+
+/** @def PDMDRV_SET_ERROR
+ * Set the VM error. See PDMDrvHlpVMSetError() for printf like message formatting.
+ */
+#define PDMDRV_SET_ERROR(pDrvIns, rc, pszError) \
+ PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, "%s", pszError)
+
+/**
+ * @copydoc PDMDRVHLP::pfnVMSetErrorV
+ */
+DECLINLINE(int) PDMDrvHlpVMSetErrorV(PPDMDRVINS pDrvIns, const int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
+}
+
+
+/**
+ * @copydoc PDMDRVHLP::pfnVMSetRuntimeError
+ */
+DECLINLINE(int) PDMDrvHlpVMSetRuntimeError(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...)
+{
+ va_list va;
+ int rc;
+ va_start(va, pszFormat);
+ rc = pDrvIns->CTX_SUFF(pHlp)->pfnVMSetRuntimeErrorV(pDrvIns, fFlags, pszErrorId, pszFormat, va);
+ va_end(va);
+ return rc;
+}
+
+/** @def PDMDRV_SET_RUNTIME_ERROR
+ * Set the VM runtime error. See PDMDrvHlpVMSetRuntimeError() for printf like message formatting.
+ */
+#define PDMDRV_SET_RUNTIME_ERROR(pDrvIns, fFlags, pszErrorId, pszError) \
+ PDMDrvHlpVMSetRuntimeError(pDrvIns, fFlags, pszErrorId, "%s", pszError)
+
+/**
+ * @copydoc PDMDRVHLP::pfnVMSetRuntimeErrorV
+ */
+DECLINLINE(int) PDMDrvHlpVMSetRuntimeErrorV(PPDMDRVINS pDrvIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnVMSetRuntimeErrorV(pDrvIns, fFlags, pszErrorId, pszFormat, va);
+}
+
+
+
+/** @def PDMDRV_ASSERT_EMT
+ * Assert that the current thread is the emulation thread.
+ */
+#ifdef VBOX_STRICT
+# define PDMDRV_ASSERT_EMT(pDrvIns) pDrvIns->CTX_SUFF(pHlp)->pfnAssertEMT(pDrvIns, __FILE__, __LINE__, __FUNCTION__)
+#else
+# define PDMDRV_ASSERT_EMT(pDrvIns) do { } while (0)
+#endif
+
+/** @def PDMDRV_ASSERT_OTHER
+ * Assert that the current thread is NOT the emulation thread.
+ */
+#ifdef VBOX_STRICT
+# define PDMDRV_ASSERT_OTHER(pDrvIns) pDrvIns->CTX_SUFF(pHlp)->pfnAssertOther(pDrvIns, __FILE__, __LINE__, __FUNCTION__)
+#else
+# define PDMDRV_ASSERT_OTHER(pDrvIns) do { } while (0)
+#endif
+
+/**
+ * @copydoc PDMDRVHLP::pfnFTSetCheckpoint
+ */
+DECLINLINE(int) PDMDrvHlpFTSetCheckpoint(PPDMDRVINS pDrvIns, FTMCHECKPOINTTYPE enmType)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnFTSetCheckpoint(pDrvIns, enmType);
+}
+
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMDRVHLP::pfnAttach
+ */
+DECLINLINE(int) PDMDrvHlpAttach(PPDMDRVINS pDrvIns, uint32_t fFlags, PPDMIBASE *ppBaseInterface)
+{
+ return pDrvIns->pHlpR3->pfnAttach(pDrvIns, fFlags, ppBaseInterface);
+}
+
+/**
+ * Check that there is no driver below the us that we should attach to.
+ *
+ * @returns VERR_PDM_NO_ATTACHED_DRIVER if there is no driver.
+ * @param pDrvIns The driver instance.
+ */
+DECLINLINE(int) PDMDrvHlpNoAttach(PPDMDRVINS pDrvIns)
+{
+ return pDrvIns->pHlpR3->pfnAttach(pDrvIns, 0, NULL);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnDetach
+ */
+DECLINLINE(int) PDMDrvHlpDetach(PPDMDRVINS pDrvIns, uint32_t fFlags)
+{
+ return pDrvIns->pHlpR3->pfnDetach(pDrvIns, fFlags);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnDetachSelf
+ */
+DECLINLINE(int) PDMDrvHlpDetachSelf(PPDMDRVINS pDrvIns, uint32_t fFlags)
+{
+ return pDrvIns->pHlpR3->pfnDetachSelf(pDrvIns, fFlags);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnMountPrepare
+ */
+DECLINLINE(int) PDMDrvHlpMountPrepare(PPDMDRVINS pDrvIns, const char *pszFilename, const char *pszCoreDriver)
+{
+ return pDrvIns->pHlpR3->pfnMountPrepare(pDrvIns, pszFilename, pszCoreDriver);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnVMState
+ */
+DECLINLINE(VMSTATE) PDMDrvHlpVMState(PPDMDRVINS pDrvIns)
+{
+ return pDrvIns->CTX_SUFF(pHlp)->pfnVMState(pDrvIns);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnVMTeleportedAndNotFullyResumedYet
+ */
+DECLINLINE(bool) PDMDrvHlpVMTeleportedAndNotFullyResumedYet(PPDMDRVINS pDrvIns)
+{
+ return pDrvIns->pHlpR3->pfnVMTeleportedAndNotFullyResumedYet(pDrvIns);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnGetSupDrvSession
+ */
+DECLINLINE(PSUPDRVSESSION) PDMDrvHlpGetSupDrvSession(PPDMDRVINS pDrvIns)
+{
+ return pDrvIns->pHlpR3->pfnGetSupDrvSession(pDrvIns);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnQueueCreate
+ */
+DECLINLINE(int) PDMDrvHlpQueueCreate(PPDMDRVINS pDrvIns, uint32_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEDRV pfnCallback, const char *pszName, PPDMQUEUE *ppQueue)
+{
+ return pDrvIns->pHlpR3->pfnQueueCreate(pDrvIns, cbItem, cItems, cMilliesInterval, pfnCallback, pszName, ppQueue);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnTMGetVirtualFreq
+ */
+DECLINLINE(uint64_t) PDMDrvHlpTMGetVirtualFreq(PPDMDRVINS pDrvIns)
+{
+ return pDrvIns->pHlpR3->pfnTMGetVirtualFreq(pDrvIns);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnTMGetVirtualTime
+ */
+DECLINLINE(uint64_t) PDMDrvHlpTMGetVirtualTime(PPDMDRVINS pDrvIns)
+{
+ return pDrvIns->pHlpR3->pfnTMGetVirtualTime(pDrvIns);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnTMTimerCreate
+ */
+DECLINLINE(int) PDMDrvHlpTMTimerCreate(PPDMDRVINS pDrvIns, TMCLOCK enmClock, PFNTMTIMERDRV pfnCallback, void *pvUser, uint32_t fFlags, const char *pszDesc, PPTMTIMERR3 ppTimer)
+{
+ return pDrvIns->pHlpR3->pfnTMTimerCreate(pDrvIns, enmClock, pfnCallback, pvUser, fFlags, pszDesc, ppTimer);
+}
+
+/**
+ * Register a save state data unit.
+ *
+ * @returns VBox status.
+ * @param pDrvIns Driver instance.
+ * @param uVersion Data layout version number.
+ * @param cbGuess The approximate amount of data in the unit.
+ * Only for progress indicators.
+ * @param pfnSaveExec Execute save callback, optional.
+ * @param pfnLoadExec Execute load callback, optional.
+ */
+DECLINLINE(int) PDMDrvHlpSSMRegister(PPDMDRVINS pDrvIns, uint32_t uVersion, size_t cbGuess,
+ PFNSSMDRVSAVEEXEC pfnSaveExec, PFNSSMDRVLOADEXEC pfnLoadExec)
+{
+ return pDrvIns->pHlpR3->pfnSSMRegister(pDrvIns, uVersion, cbGuess,
+ NULL /*pfnLivePrep*/, NULL /*pfnLiveExec*/, NULL /*pfnLiveVote*/,
+ NULL /*pfnSavePrep*/, pfnSaveExec, NULL /*pfnSaveDone*/,
+ NULL /*pfnLoadPrep*/, pfnLoadExec, NULL /*pfnLoadDone*/);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnSSMRegister
+ */
+DECLINLINE(int) PDMDrvHlpSSMRegisterEx(PPDMDRVINS pDrvIns, uint32_t uVersion, size_t cbGuess,
+ PFNSSMDRVLIVEPREP pfnLivePrep, PFNSSMDRVLIVEEXEC pfnLiveExec, PFNSSMDRVLIVEVOTE pfnLiveVote,
+ PFNSSMDRVSAVEPREP pfnSavePrep, PFNSSMDRVSAVEEXEC pfnSaveExec, PFNSSMDRVSAVEDONE pfnSaveDone,
+ PFNSSMDRVLOADPREP pfnLoadPrep, PFNSSMDRVLOADEXEC pfnLoadExec, PFNSSMDRVLOADDONE pfnLoadDone)
+{
+ return pDrvIns->pHlpR3->pfnSSMRegister(pDrvIns, uVersion, cbGuess,
+ pfnLivePrep, pfnLiveExec, pfnLiveVote,
+ pfnSavePrep, pfnSaveExec, pfnSaveDone,
+ pfnLoadPrep, pfnLoadExec, pfnLoadDone);
+}
+
+/**
+ * Register a load done callback.
+ *
+ * @returns VBox status.
+ * @param pDrvIns Driver instance.
+ * @param pfnLoadDone Done load callback, optional.
+ */
+DECLINLINE(int) PDMDrvHlpSSMRegisterLoadDone(PPDMDRVINS pDrvIns, PFNSSMDRVLOADDONE pfnLoadDone)
+{
+ return pDrvIns->pHlpR3->pfnSSMRegister(pDrvIns, 0 /*uVersion*/, 0 /*cbGuess*/,
+ NULL /*pfnLivePrep*/, NULL /*pfnLiveExec*/, NULL /*pfnLiveVote*/,
+ NULL /*pfnSavePrep*/, NULL /*pfnSaveExec*/, NULL /*pfnSaveDone*/,
+ NULL /*pfnLoadPrep*/, NULL /*pfnLoadExec*/, pfnLoadDone);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnDBGFInfoRegister
+ */
+DECLINLINE(int) PDMDrvHlpDBGFInfoRegister(PPDMDRVINS pDrvIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDRV pfnHandler)
+{
+ return pDrvIns->pHlpR3->pfnDBGFInfoRegister(pDrvIns, pszName, pszDesc, pfnHandler);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnDBGFInfoDeregister
+ */
+DECLINLINE(int) PDMDrvHlpDBGFInfoDeregister(PPDMDRVINS pDrvIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDRV pfnHandler)
+{
+ return pDrvIns->pHlpR3->pfnDBGFInfoRegister(pDrvIns, pszName, pszDesc, pfnHandler);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnSTAMRegister
+ */
+DECLINLINE(void) PDMDrvHlpSTAMRegister(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
+{
+ pDrvIns->pHlpR3->pfnSTAMRegister(pDrvIns, pvSample, enmType, pszName, enmUnit, pszDesc);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnSTAMRegisterF
+ */
+DECLINLINE(void) PDMDrvHlpSTAMRegisterF(PPDMDRVINS pDrvIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ const char *pszDesc, const char *pszName, ...)
+{
+ va_list va;
+ va_start(va, pszName);
+ pDrvIns->pHlpR3->pfnSTAMRegisterV(pDrvIns, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, va);
+ va_end(va);
+}
+
+/**
+ * Convenience wrapper that registers counter which is always visible.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pCounter Pointer to the counter variable.
+ * @param pszName The name of the sample. This is prefixed with
+ * "/Drivers/<drivername>-<instance no>/".
+ * @param enmUnit The unit.
+ * @param pszDesc The description.
+ */
+DECLINLINE(void) PDMDrvHlpSTAMRegCounterEx(PPDMDRVINS pDrvIns, PSTAMCOUNTER pCounter, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
+{
+ pDrvIns->pHlpR3->pfnSTAMRegisterF(pDrvIns, pCounter, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, enmUnit, pszDesc,
+ "/Drivers/%s-%u/%s", pDrvIns->pReg->szName, pDrvIns->iInstance, pszName);
+}
+
+/**
+ * Convenience wrapper that registers counter which is always visible and has
+ * the STAMUNIT_COUNT unit.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pCounter Pointer to the counter variable.
+ * @param pszName The name of the sample. This is prefixed with
+ * "/Drivers/<drivername>-<instance no>/".
+ * @param pszDesc The description.
+ */
+DECLINLINE(void) PDMDrvHlpSTAMRegCounter(PPDMDRVINS pDrvIns, PSTAMCOUNTER pCounter, const char *pszName, const char *pszDesc)
+{
+ PDMDrvHlpSTAMRegCounterEx(pDrvIns, pCounter, pszName, STAMUNIT_COUNT, pszDesc);
+}
+
+/**
+ * Convenience wrapper that registers profiling sample which is always visible.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pProfile Pointer to the profiling variable.
+ * @param pszName The name of the sample. This is prefixed with
+ * "/Drivers/<drivername>-<instance no>/".
+ * @param enmUnit The unit.
+ * @param pszDesc The description.
+ */
+DECLINLINE(void) PDMDrvHlpSTAMRegProfileEx(PPDMDRVINS pDrvIns, PSTAMPROFILE pProfile, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
+{
+ pDrvIns->pHlpR3->pfnSTAMRegisterF(pDrvIns, pProfile, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, enmUnit, pszDesc,
+ "/Drivers/%s-%u/%s", pDrvIns->pReg->szName, pDrvIns->iInstance, pszName);
+}
+
+/**
+ * Convenience wrapper that registers profiling sample which is always visible
+ * hand counts ticks per call (STAMUNIT_TICKS_PER_CALL).
+ *
+ * @param pDrvIns The driver instance.
+ * @param pProfile Pointer to the profiling variable.
+ * @param pszName The name of the sample. This is prefixed with
+ * "/Drivers/<drivername>-<instance no>/".
+ * @param pszDesc The description.
+ */
+DECLINLINE(void) PDMDrvHlpSTAMRegProfile(PPDMDRVINS pDrvIns, PSTAMPROFILE pProfile, const char *pszName, const char *pszDesc)
+{
+ PDMDrvHlpSTAMRegProfileEx(pDrvIns, pProfile, pszName, STAMUNIT_TICKS_PER_CALL, pszDesc);
+}
+
+/**
+ * Convenience wrapper that registers an advanced profiling sample which is
+ * always visible.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pProfile Pointer to the profiling variable.
+ * @param enmUnit The unit.
+ * @param pszName The name of the sample. This is prefixed with
+ * "/Drivers/<drivername>-<instance no>/".
+ * @param pszDesc The description.
+ */
+DECLINLINE(void) PDMDrvHlpSTAMRegProfileAdvEx(PPDMDRVINS pDrvIns, PSTAMPROFILEADV pProfile, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
+{
+ pDrvIns->pHlpR3->pfnSTAMRegisterF(pDrvIns, pProfile, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, enmUnit, pszDesc,
+ "/Drivers/%s-%u/%s", pDrvIns->pReg->szName, pDrvIns->iInstance, pszName);
+}
+
+/**
+ * Convenience wrapper that registers an advanced profiling sample which is
+ * always visible.
+ *
+ * @param pDrvIns The driver instance.
+ * @param pProfile Pointer to the profiling variable.
+ * @param pszName The name of the sample. This is prefixed with
+ * "/Drivers/<drivername>-<instance no>/".
+ * @param pszDesc The description.
+ */
+DECLINLINE(void) PDMDrvHlpSTAMRegProfileAdv(PPDMDRVINS pDrvIns, PSTAMPROFILEADV pProfile, const char *pszName, const char *pszDesc)
+{
+ PDMDrvHlpSTAMRegProfileAdvEx(pDrvIns, pProfile, pszName, STAMUNIT_TICKS_PER_CALL, pszDesc);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnSTAMDeregister
+ */
+DECLINLINE(int) PDMDrvHlpSTAMDeregister(PPDMDRVINS pDrvIns, void *pvSample)
+{
+ return pDrvIns->pHlpR3->pfnSTAMDeregister(pDrvIns, pvSample);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnSUPCallVMMR0Ex
+ */
+DECLINLINE(int) PDMDrvHlpSUPCallVMMR0Ex(PPDMDRVINS pDrvIns, unsigned uOperation, void *pvArg, unsigned cbArg)
+{
+ return pDrvIns->pHlpR3->pfnSUPCallVMMR0Ex(pDrvIns, uOperation, pvArg, cbArg);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnUSBRegisterHub
+ */
+DECLINLINE(int) PDMDrvHlpUSBRegisterHub(PPDMDRVINS pDrvIns, uint32_t fVersions, uint32_t cPorts, PCPDMUSBHUBREG pUsbHubReg, PPCPDMUSBHUBHLP ppUsbHubHlp)
+{
+ return pDrvIns->pHlpR3->pfnUSBRegisterHub(pDrvIns, fVersions, cPorts, pUsbHubReg, ppUsbHubHlp);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnSetAsyncNotification
+ */
+DECLINLINE(int) PDMDrvHlpSetAsyncNotification(PPDMDRVINS pDrvIns, PFNPDMDRVASYNCNOTIFY pfnAsyncNotify)
+{
+ return pDrvIns->pHlpR3->pfnSetAsyncNotification(pDrvIns, pfnAsyncNotify);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnAsyncNotificationCompleted
+ */
+DECLINLINE(void) PDMDrvHlpAsyncNotificationCompleted(PPDMDRVINS pDrvIns)
+{
+ pDrvIns->pHlpR3->pfnAsyncNotificationCompleted(pDrvIns);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnThreadCreate
+ */
+DECLINLINE(int) PDMDrvHlpThreadCreate(PPDMDRVINS pDrvIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDRV pfnThread,
+ PFNPDMTHREADWAKEUPDRV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
+{
+ return pDrvIns->pHlpR3->pfnThreadCreate(pDrvIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
+}
+
+# ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
+/**
+ * @copydoc PDMDRVHLP::pfnAsyncCompletionTemplateCreate
+ */
+DECLINLINE(int) PDMDrvHlpAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
+ PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser, const char *pszDesc)
+{
+ return pDrvIns->pHlpR3->pfnAsyncCompletionTemplateCreate(pDrvIns, ppTemplate, pfnCompleted, pvTemplateUser, pszDesc);
+}
+# endif
+
+# ifdef VBOX_WITH_NETSHAPER
+/**
+ * @copydoc PDMDRVHLP::pfnNetShaperAttach
+ */
+DECLINLINE(int) PDMDrvHlpNetShaperAttach(PPDMDRVINS pDrvIns, const char *pcszBwGroup, PPDMNSFILTER pFilter)
+{
+ return pDrvIns->pHlpR3->pfnNetShaperAttach(pDrvIns, pcszBwGroup, pFilter);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnNetShaperDetach
+ */
+DECLINLINE(int) PDMDrvHlpNetShaperDetach(PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter)
+{
+ return pDrvIns->pHlpR3->pfnNetShaperDetach(pDrvIns, pFilter);
+}
+# endif
+
+/**
+ * @copydoc PDMDRVHLP::pfnCritSectInit
+ */
+DECLINLINE(int) PDMDrvHlpCritSectInit(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL, const char *pszName)
+{
+ return pDrvIns->pHlpR3->pfnCritSectInit(pDrvIns, pCritSect, RT_SRC_POS_ARGS, pszName);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnCallR0
+ */
+DECLINLINE(int) PDMDrvHlpCallR0(PPDMDRVINS pDrvIns, uint32_t uOperation, uint64_t u64Arg)
+{
+ return pDrvIns->pHlpR3->pfnCallR0(pDrvIns, uOperation, u64Arg);
+}
+
+/**
+ * @copydoc PDMDRVHLP::pfnBlkCacheRetain
+ */
+DECLINLINE(int) PDMDrvHlpBlkCacheRetain(PPDMDRVINS pDrvIns, PPPDMBLKCACHE ppBlkCache,
+ PFNPDMBLKCACHEXFERCOMPLETEDRV pfnXferComplete,
+ PFNPDMBLKCACHEXFERENQUEUEDRV pfnXferEnqueue,
+ PFNPDMBLKCACHEXFERENQUEUEDISCARDDRV pfnXferEnqueueDiscard,
+ const char *pcszId)
+{
+ return pDrvIns->pHlpR3->pfnBlkCacheRetain(pDrvIns, ppBlkCache, pfnXferComplete, pfnXferEnqueue, pfnXferEnqueueDiscard, pcszId);
+}
+
+/** Pointer to callbacks provided to the VBoxDriverRegister() call. */
+typedef struct PDMDRVREGCB *PPDMDRVREGCB;
+/** Pointer to const callbacks provided to the VBoxDriverRegister() call. */
+typedef const struct PDMDRVREGCB *PCPDMDRVREGCB;
+
+/**
+ * Callbacks for VBoxDriverRegister().
+ */
+typedef struct PDMDRVREGCB
+{
+ /** Interface version.
+ * This is set to PDM_DRVREG_CB_VERSION. */
+ uint32_t u32Version;
+
+ /**
+ * Registers a driver with the current VM instance.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param pReg Pointer to the driver registration record.
+ * This data must be permanent and readonly.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegister,(PCPDMDRVREGCB pCallbacks, PCPDMDRVREG pReg));
+} PDMDRVREGCB;
+
+/** Current version of the PDMDRVREGCB structure. */
+#define PDM_DRVREG_CB_VERSION PDM_VERSION_MAKE(0xf0fa, 1, 0)
+
+
+/**
+ * The VBoxDriverRegister callback function.
+ *
+ * PDM will invoke this function after loading a driver module and letting
+ * the module decide which drivers to register and how to handle conflicts.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param u32Version VBox version number.
+ */
+typedef DECLCALLBACK(int) FNPDMVBOXDRIVERSREGISTER(PCPDMDRVREGCB pCallbacks, uint32_t u32Version);
+
+VMMR3DECL(int) PDMR3DrvStaticRegistration(PVM pVM, FNPDMVBOXDRIVERSREGISTER pfnCallback);
+
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
diff --git a/include/VBox/vmm/pdmifs.h b/include/VBox/vmm/pdmifs.h
new file mode 100644
index 00000000..17dba105
--- /dev/null
+++ b/include/VBox/vmm/pdmifs.h
@@ -0,0 +1,2996 @@
+/** @file
+ * PDM - Pluggable Device Manager, Interfaces.
+ */
+
+/*
+ * Copyright (C) 2006-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmifs_h
+#define ___VBox_vmm_pdmifs_h
+
+#include <iprt/sg.h>
+#include <VBox/types.h>
+#include <VBox/hgcmsvc.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_interfaces The PDM Interface Definitions
+ * @ingroup grp_pdm
+ *
+ * For historical reasons (the PDMINTERFACE enum) a lot of interface was stuffed
+ * together in this group instead, dragging stuff into global space that didn't
+ * need to be there and making this file huge (>2500 lines). Since we're using
+ * UUIDs as interface identifiers (IIDs) now, no only generic PDM interface will
+ * be added to this file. Component specific interface should be defined in the
+ * header file of that component.
+ *
+ * Interfaces consists of a method table (typedef'ed struct) and an interface
+ * ID. The typename of the method table should have an 'I' in it, be all
+ * capitals and according to the rules, no underscores. The interface ID is a
+ * \#define constructed by appending '_IID' to the typename. The IID value is a
+ * UUID string on the form "a2299c0d-b709-4551-aa5a-73f59ffbed74". If you stick
+ * to these rules, you can make use of the PDMIBASE_QUERY_INTERFACE and
+ * PDMIBASE_RETURN_INTERFACE when querying interface and implementing
+ * PDMIBASE::pfnQueryInterface respectively.
+ *
+ * In most interface descriptions the orientation of the interface is given as
+ * 'down' or 'up'. This refers to a model with the device on the top and the
+ * drivers stacked below it. Sometimes there is mention of 'main' or 'external'
+ * which normally means the same, i.e. the Main or VBoxBFE API. Picture the
+ * orientation of 'main' as horizontal.
+ *
+ * @{
+ */
+
+
+/** @name PDMIBASE
+ * @{
+ */
+
+/**
+ * PDM Base Interface.
+ *
+ * Everyone implements this.
+ */
+typedef struct PDMIBASE
+{
+ /**
+ * Queries an interface to the driver.
+ *
+ * @returns Pointer to interface.
+ * @returns NULL if the interface was not supported by the driver.
+ * @param pInterface Pointer to this interface structure.
+ * @param pszIID The interface ID, a UUID string.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(void *, pfnQueryInterface,(struct PDMIBASE *pInterface, const char *pszIID));
+} PDMIBASE;
+/** PDMIBASE interface ID. */
+#define PDMIBASE_IID "a2299c0d-b709-4551-aa5a-73f59ffbed74"
+
+/**
+ * Helper macro for querying an interface from PDMIBASE.
+ *
+ * @returns Correctly typed PDMIBASE::pfnQueryInterface return value.
+ *
+ * @param pIBase Pointer to the base interface.
+ * @param InterfaceType The interface type name. The interface ID is
+ * derived from this by appending _IID.
+ */
+#define PDMIBASE_QUERY_INTERFACE(pIBase, InterfaceType) \
+ ( (InterfaceType *)(pIBase)->pfnQueryInterface(pIBase, InterfaceType##_IID ) )
+
+/**
+ * Helper macro for implementing PDMIBASE::pfnQueryInterface.
+ *
+ * Return @a pInterface if @a pszIID matches the @a InterfaceType. This will
+ * perform basic type checking.
+ *
+ * @param pszIID The ID of the interface that is being queried.
+ * @param InterfaceType The interface type name. The interface ID is
+ * derived from this by appending _IID.
+ * @param pInterface The interface address expression.
+ */
+#define PDMIBASE_RETURN_INTERFACE(pszIID, InterfaceType, pInterface) \
+ do { \
+ if (RTUuidCompare2Strs((pszIID), InterfaceType##_IID) == 0) \
+ { \
+ P##InterfaceType pReturnInterfaceTypeCheck = (pInterface); \
+ return pReturnInterfaceTypeCheck; \
+ } \
+ } while (0)
+
+/** @} */
+
+
+/** @name PDMIBASERC
+ * @{
+ */
+
+/**
+ * PDM Base Interface for querying ring-mode context interfaces in
+ * ring-3.
+ *
+ * This is mandatory for drivers present in raw-mode context.
+ */
+typedef struct PDMIBASERC
+{
+ /**
+ * Queries an ring-mode context interface to the driver.
+ *
+ * @returns Pointer to interface.
+ * @returns NULL if the interface was not supported by the driver.
+ * @param pInterface Pointer to this interface structure.
+ * @param pszIID The interface ID, a UUID string.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(RTRCPTR, pfnQueryInterface,(struct PDMIBASERC *pInterface, const char *pszIID));
+} PDMIBASERC;
+/** Pointer to a PDM Base Interface for query ring-mode context interfaces. */
+typedef PDMIBASERC *PPDMIBASERC;
+/** PDMIBASERC interface ID. */
+#define PDMIBASERC_IID "f6a6c649-6cb3-493f-9737-4653f221aeca"
+
+/**
+ * Helper macro for querying an interface from PDMIBASERC.
+ *
+ * @returns PDMIBASERC::pfnQueryInterface return value.
+ *
+ * @param pIBaseRC Pointer to the base raw-mode context interface. Can
+ * be NULL.
+ * @param InterfaceType The interface type base name, no trailing RC. The
+ * interface ID is derived from this by appending _IID.
+ *
+ * @remarks Unlike PDMIBASE_QUERY_INTERFACE, this macro is not able to do any
+ * implicit type checking for you.
+ */
+#define PDMIBASERC_QUERY_INTERFACE(pIBaseRC, InterfaceType) \
+ ( (P##InterfaceType##RC)((pIBaseRC) ? (pIBaseRC)->pfnQueryInterface(pIBaseRC, InterfaceType##_IID) : NIL_RTRCPTR) )
+
+/**
+ * Helper macro for implementing PDMIBASERC::pfnQueryInterface.
+ *
+ * Return @a pInterface if @a pszIID matches the @a InterfaceType. This will
+ * perform basic type checking.
+ *
+ * @param pIns Pointer to the instance data.
+ * @param pszIID The ID of the interface that is being queried.
+ * @param InterfaceType The interface type base name, no trailing RC. The
+ * interface ID is derived from this by appending _IID.
+ * @param pInterface The interface address expression. This must resolve
+ * to some address within the instance data.
+ * @remarks Don't use with PDMIBASE.
+ */
+#define PDMIBASERC_RETURN_INTERFACE(pIns, pszIID, InterfaceType, pInterface) \
+ do { \
+ Assert((uintptr_t)pInterface - PDMINS_2_DATA(pIns, uintptr_t) < _4M); \
+ if (RTUuidCompare2Strs((pszIID), InterfaceType##_IID) == 0) \
+ { \
+ InterfaceType##RC *pReturnInterfaceTypeCheck = (pInterface); \
+ return (uintptr_t)pReturnInterfaceTypeCheck \
+ - PDMINS_2_DATA(pIns, uintptr_t) \
+ + PDMINS_2_DATA_RCPTR(pIns); \
+ } \
+ } while (0)
+
+/** @} */
+
+
+/** @name PDMIBASER0
+ * @{
+ */
+
+/**
+ * PDM Base Interface for querying ring-0 interfaces in ring-3.
+ *
+ * This is mandatory for drivers present in ring-0 context.
+ */
+typedef struct PDMIBASER0
+{
+ /**
+ * Queries an ring-0 interface to the driver.
+ *
+ * @returns Pointer to interface.
+ * @returns NULL if the interface was not supported by the driver.
+ * @param pInterface Pointer to this interface structure.
+ * @param pszIID The interface ID, a UUID string.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(RTR0PTR, pfnQueryInterface,(struct PDMIBASER0 *pInterface, const char *pszIID));
+} PDMIBASER0;
+/** Pointer to a PDM Base Interface for query ring-0 context interfaces. */
+typedef PDMIBASER0 *PPDMIBASER0;
+/** PDMIBASER0 interface ID. */
+#define PDMIBASER0_IID "9c9b99b8-7f53-4f59-a3c2-5bc9659c7944"
+
+/**
+ * Helper macro for querying an interface from PDMIBASER0.
+ *
+ * @returns PDMIBASER0::pfnQueryInterface return value.
+ *
+ * @param pIBaseR0 Pointer to the base ring-0 interface. Can be NULL.
+ * @param InterfaceType The interface type base name, no trailing R0. The
+ * interface ID is derived from this by appending _IID.
+ *
+ * @remarks Unlike PDMIBASE_QUERY_INTERFACE, this macro is not able to do any
+ * implicit type checking for you.
+ */
+#define PDMIBASER0_QUERY_INTERFACE(pIBaseR0, InterfaceType) \
+ ( (P##InterfaceType##R0)((pIBaseR0) ? (pIBaseR0)->pfnQueryInterface(pIBaseR0, InterfaceType##_IID) : NIL_RTR0PTR) )
+
+/**
+ * Helper macro for implementing PDMIBASER0::pfnQueryInterface.
+ *
+ * Return @a pInterface if @a pszIID matches the @a InterfaceType. This will
+ * perform basic type checking.
+ *
+ * @param pIns Pointer to the instance data.
+ * @param pszIID The ID of the interface that is being queried.
+ * @param InterfaceType The interface type base name, no trailing R0. The
+ * interface ID is derived from this by appending _IID.
+ * @param pInterface The interface address expression. This must resolve
+ * to some address within the instance data.
+ * @remarks Don't use with PDMIBASE.
+ */
+#define PDMIBASER0_RETURN_INTERFACE(pIns, pszIID, InterfaceType, pInterface) \
+ do { \
+ Assert((uintptr_t)pInterface - PDMINS_2_DATA(pIns, uintptr_t) < _4M); \
+ if (RTUuidCompare2Strs((pszIID), InterfaceType##_IID) == 0) \
+ { \
+ InterfaceType##R0 *pReturnInterfaceTypeCheck = (pInterface); \
+ return (uintptr_t)pReturnInterfaceTypeCheck \
+ - PDMINS_2_DATA(pIns, uintptr_t) \
+ + PDMINS_2_DATA_R0PTR(pIns); \
+ } \
+ } while (0)
+
+/** @} */
+
+
+/**
+ * Dummy interface.
+ *
+ * This is used to typedef other dummy interfaces. The purpose of a dummy
+ * interface is to validate the logical function of a driver/device and
+ * full a natural interface pair.
+ */
+typedef struct PDMIDUMMY
+{
+ RTHCPTR pvDummy;
+} PDMIDUMMY;
+
+
+/** Pointer to a mouse port interface. */
+typedef struct PDMIMOUSEPORT *PPDMIMOUSEPORT;
+/**
+ * Mouse port interface (down).
+ * Pair with PDMIMOUSECONNECTOR.
+ */
+typedef struct PDMIMOUSEPORT
+{
+ /**
+ * Puts a mouse event.
+ *
+ * This is called by the source of mouse events. The event will be passed up
+ * until the topmost driver, which then calls the registered event handler.
+ *
+ * @returns VBox status code. Return VERR_TRY_AGAIN if you cannot process the
+ * event now and want it to be repeated at a later point.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param iDeltaX The X delta.
+ * @param iDeltaY The Y delta.
+ * @param iDeltaZ The Z delta.
+ * @param iDeltaW The W (horizontal scroll button) delta.
+ * @param fButtonStates The button states, see the PDMIMOUSEPORT_BUTTON_* \#defines.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPutEvent,(PPDMIMOUSEPORT pInterface, int32_t iDeltaX, int32_t iDeltaY, int32_t iDeltaZ, int32_t iDeltaW, uint32_t fButtonStates));
+ /**
+ * Puts an absolute mouse event.
+ *
+ * This is called by the source of mouse events. The event will be passed up
+ * until the topmost driver, which then calls the registered event handler.
+ *
+ * @returns VBox status code. Return VERR_TRY_AGAIN if you cannot process the
+ * event now and want it to be repeated at a later point.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param uX The X value, in the range 0 to 0xffff.
+ * @param uY The Y value, in the range 0 to 0xffff.
+ * @param iDeltaZ The Z delta.
+ * @param iDeltaW The W (horizontal scroll button) delta.
+ * @param fButtonStates The button states, see the PDMIMOUSEPORT_BUTTON_* \#defines.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPutEventAbs,(PPDMIMOUSEPORT pInterface, uint32_t uX, uint32_t uY, int32_t iDeltaZ, int32_t iDeltaW, uint32_t fButtonStates));
+} PDMIMOUSEPORT;
+/** PDMIMOUSEPORT interface ID. */
+#define PDMIMOUSEPORT_IID "442136fe-6f3c-49ec-9964-259b378ffa64"
+
+/** Mouse button defines for PDMIMOUSEPORT::pfnPutEvent.
+ * @{ */
+#define PDMIMOUSEPORT_BUTTON_LEFT RT_BIT(0)
+#define PDMIMOUSEPORT_BUTTON_RIGHT RT_BIT(1)
+#define PDMIMOUSEPORT_BUTTON_MIDDLE RT_BIT(2)
+#define PDMIMOUSEPORT_BUTTON_X1 RT_BIT(3)
+#define PDMIMOUSEPORT_BUTTON_X2 RT_BIT(4)
+/** @} */
+
+
+/** Pointer to a mouse connector interface. */
+typedef struct PDMIMOUSECONNECTOR *PPDMIMOUSECONNECTOR;
+/**
+ * Mouse connector interface (up).
+ * Pair with PDMIMOUSEPORT.
+ */
+typedef struct PDMIMOUSECONNECTOR
+{
+ /**
+ * Notifies the the downstream driver of changes to the reporting modes
+ * supported by the driver
+ *
+ * @param pInterface Pointer to the this interface.
+ * @param fRelative Whether relative mode is currently supported.
+ * @param fAbsolute Whether absolute mode is currently supported.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnReportModes,(PPDMIMOUSECONNECTOR pInterface, bool fRelative, bool fAbsolute));
+
+} PDMIMOUSECONNECTOR;
+/** PDMIMOUSECONNECTOR interface ID. */
+#define PDMIMOUSECONNECTOR_IID "ce64d7bd-fa8f-41d1-a6fb-d102a2d6bffe"
+
+
+/** Pointer to a keyboard port interface. */
+typedef struct PDMIKEYBOARDPORT *PPDMIKEYBOARDPORT;
+/**
+ * Keyboard port interface (down).
+ * Pair with PDMIKEYBOARDCONNECTOR.
+ */
+typedef struct PDMIKEYBOARDPORT
+{
+ /**
+ * Puts a keyboard event.
+ *
+ * This is called by the source of keyboard events. The event will be passed up
+ * until the topmost driver, which then calls the registered event handler.
+ *
+ * @returns VBox status code. Return VERR_TRY_AGAIN if you cannot process the
+ * event now and want it to be repeated at a later point.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param u8KeyCode The keycode to queue.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPutEvent,(PPDMIKEYBOARDPORT pInterface, uint8_t u8KeyCode));
+} PDMIKEYBOARDPORT;
+/** PDMIKEYBOARDPORT interface ID. */
+#define PDMIKEYBOARDPORT_IID "2a0844f0-410b-40ab-a6ed-6575f3aa3e29"
+
+
+/**
+ * Keyboard LEDs.
+ */
+typedef enum PDMKEYBLEDS
+{
+ /** No leds. */
+ PDMKEYBLEDS_NONE = 0x0000,
+ /** Num Lock */
+ PDMKEYBLEDS_NUMLOCK = 0x0001,
+ /** Caps Lock */
+ PDMKEYBLEDS_CAPSLOCK = 0x0002,
+ /** Scroll Lock */
+ PDMKEYBLEDS_SCROLLLOCK = 0x0004
+} PDMKEYBLEDS;
+
+/** Pointer to keyboard connector interface. */
+typedef struct PDMIKEYBOARDCONNECTOR *PPDMIKEYBOARDCONNECTOR;
+/**
+ * Keyboard connector interface (up).
+ * Pair with PDMIKEYBOARDPORT
+ */
+typedef struct PDMIKEYBOARDCONNECTOR
+{
+ /**
+ * Notifies the the downstream driver about an LED change initiated by the guest.
+ *
+ * @param pInterface Pointer to the this interface.
+ * @param enmLeds The new led mask.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnLedStatusChange,(PPDMIKEYBOARDCONNECTOR pInterface, PDMKEYBLEDS enmLeds));
+
+ /**
+ * Notifies the the downstream driver of changes in driver state.
+ *
+ * @param pInterface Pointer to the this interface.
+ * @param fActive Whether interface wishes to get "focus".
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetActive,(PPDMIKEYBOARDCONNECTOR pInterface, bool fActive));
+
+} PDMIKEYBOARDCONNECTOR;
+/** PDMIKEYBOARDCONNECTOR interface ID. */
+#define PDMIKEYBOARDCONNECTOR_IID "db3f7bd5-953e-436f-9f8e-077905a92d82"
+
+
+
+/** Pointer to a display port interface. */
+typedef struct PDMIDISPLAYPORT *PPDMIDISPLAYPORT;
+/**
+ * Display port interface (down).
+ * Pair with PDMIDISPLAYCONNECTOR.
+ */
+typedef struct PDMIDISPLAYPORT
+{
+ /**
+ * Update the display with any changed regions.
+ *
+ * Flushes any display changes to the memory pointed to by the
+ * PDMIDISPLAYCONNECTOR interface and calles PDMIDISPLAYCONNECTOR::pfnUpdateRect()
+ * while doing so.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUpdateDisplay,(PPDMIDISPLAYPORT pInterface));
+
+ /**
+ * Update the entire display.
+ *
+ * Flushes the entire display content to the memory pointed to by the
+ * PDMIDISPLAYCONNECTOR interface and calles PDMIDISPLAYCONNECTOR::pfnUpdateRect().
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUpdateDisplayAll,(PPDMIDISPLAYPORT pInterface));
+
+ /**
+ * Return the current guest color depth in bits per pixel (bpp).
+ *
+ * As the graphics card is able to provide display updates with the bpp
+ * requested by the host, this method can be used to query the actual
+ * guest color depth.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pcBits Where to store the current guest color depth.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryColorDepth,(PPDMIDISPLAYPORT pInterface, uint32_t *pcBits));
+
+ /**
+ * Sets the refresh rate and restart the timer.
+ * The rate is defined as the minimum interval between the return of
+ * one PDMIDISPLAYPORT::pfnRefresh() call to the next one.
+ *
+ * The interval timer will be restarted by this call. So at VM startup
+ * this function must be called to start the refresh cycle. The refresh
+ * rate is not saved, but have to be when resuming a loaded VM state.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param cMilliesInterval Number of millis between two refreshes.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetRefreshRate,(PPDMIDISPLAYPORT pInterface, uint32_t cMilliesInterval));
+
+ /**
+ * Create a 32-bbp screenshot of the display.
+ *
+ * This will allocate and return a 32-bbp bitmap. Size of the bitmap scanline in bytes is 4*width.
+ *
+ * The allocated bitmap buffer must be freed with pfnFreeScreenshot.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param ppu8Data Where to store the pointer to the allocated buffer.
+ * @param pcbData Where to store the actual size of the bitmap.
+ * @param pcx Where to store the width of the bitmap.
+ * @param pcy Where to store the height of the bitmap.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTakeScreenshot,(PPDMIDISPLAYPORT pInterface, uint8_t **ppu8Data, size_t *pcbData, uint32_t *pcx, uint32_t *pcy));
+
+ /**
+ * Free screenshot buffer.
+ *
+ * This will free the memory buffer allocated by pfnTakeScreenshot.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param ppu8Data Pointer to the buffer returned by pfnTakeScreenshot.
+ * @thread Any.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnFreeScreenshot,(PPDMIDISPLAYPORT pInterface, uint8_t *pu8Data));
+
+ /**
+ * Copy bitmap to the display.
+ *
+ * This will convert and copy a 32-bbp bitmap (with dword aligned scanline length) to
+ * the memory pointed to by the PDMIDISPLAYCONNECTOR interface.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pvData Pointer to the bitmap bits.
+ * @param x The upper left corner x coordinate of the destination rectangle.
+ * @param y The upper left corner y coordinate of the destination rectangle.
+ * @param cx The width of the source and destination rectangles.
+ * @param cy The height of the source and destination rectangles.
+ * @thread The emulation thread.
+ * @remark This is just a convenience for using the bitmap conversions of the
+ * graphics device.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDisplayBlt,(PPDMIDISPLAYPORT pInterface, const void *pvData, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy));
+
+ /**
+ * Render a rectangle from guest VRAM to Framebuffer.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param x The upper left corner x coordinate of the rectangle to be updated.
+ * @param y The upper left corner y coordinate of the rectangle to be updated.
+ * @param cx The width of the rectangle to be updated.
+ * @param cy The height of the rectangle to be updated.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdateDisplayRect,(PPDMIDISPLAYPORT pInterface, int32_t x, int32_t y, uint32_t cx, uint32_t cy));
+
+ /**
+ * Inform the VGA device whether the Display is directly using the guest VRAM and there is no need
+ * to render the VRAM to the framebuffer memory.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param fRender Whether the VRAM content must be rendered to the framebuffer.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetRenderVRAM,(PPDMIDISPLAYPORT pInterface, bool fRender));
+
+ /**
+ * Render a bitmap rectangle from source to target buffer.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param cx The width of the rectangle to be copied.
+ * @param cy The height of the rectangle to be copied.
+ * @param pbSrc Source frame buffer 0,0.
+ * @param xSrc The upper left corner x coordinate of the source rectangle.
+ * @param ySrc The upper left corner y coordinate of the source rectangle.
+ * @param cxSrc The width of the source frame buffer.
+ * @param cySrc The height of the source frame buffer.
+ * @param cbSrcLine The line length of the source frame buffer.
+ * @param cSrcBitsPerPixel The pixel depth of the source.
+ * @param pbDst Destination frame buffer 0,0.
+ * @param xDst The upper left corner x coordinate of the destination rectangle.
+ * @param yDst The upper left corner y coordinate of the destination rectangle.
+ * @param cxDst The width of the destination frame buffer.
+ * @param cyDst The height of the destination frame buffer.
+ * @param cbDstLine The line length of the destination frame buffer.
+ * @param cDstBitsPerPixel The pixel depth of the destination.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCopyRect,(PPDMIDISPLAYPORT pInterface, uint32_t cx, uint32_t cy,
+ const uint8_t *pbSrc, int32_t xSrc, int32_t ySrc, uint32_t cxSrc, uint32_t cySrc, uint32_t cbSrcLine, uint32_t cSrcBitsPerPixel,
+ uint8_t *pbDst, int32_t xDst, int32_t yDst, uint32_t cxDst, uint32_t cyDst, uint32_t cbDstLine, uint32_t cDstBitsPerPixel));
+
+} PDMIDISPLAYPORT;
+/** PDMIDISPLAYPORT interface ID. */
+#define PDMIDISPLAYPORT_IID "22d3d93d-3407-487a-8308-85367eae00bb"
+
+
+typedef struct VBOXVHWACMD *PVBOXVHWACMD; /**< @todo r=bird: A line what it is to make doxygen happy. */
+typedef struct VBVACMDHDR *PVBVACMDHDR;
+typedef struct VBVAINFOSCREEN *PVBVAINFOSCREEN;
+typedef struct VBVAINFOVIEW *PVBVAINFOVIEW;
+typedef struct VBVAHOSTFLAGS *PVBVAHOSTFLAGS;
+typedef struct VBOXVDMACMD_CHROMIUM_CMD *PVBOXVDMACMD_CHROMIUM_CMD; /* <- chromium [hgsmi] command */
+typedef struct VBOXVDMACMD_CHROMIUM_CTL *PVBOXVDMACMD_CHROMIUM_CTL; /* <- chromium [hgsmi] command */
+
+/** Pointer to a display connector interface. */
+typedef struct PDMIDISPLAYCONNECTOR *PPDMIDISPLAYCONNECTOR;
+/**
+ * Display connector interface (up).
+ * Pair with PDMIDISPLAYPORT.
+ */
+typedef struct PDMIDISPLAYCONNECTOR
+{
+ /**
+ * Resize the display.
+ * This is called when the resolution changes. This usually happens on
+ * request from the guest os, but may also happen as the result of a reset.
+ * If the callback returns VINF_VGA_RESIZE_IN_PROGRESS, the caller (VGA device)
+ * must not access the connector and return.
+ *
+ * @returns VINF_SUCCESS if the framebuffer resize was completed,
+ * VINF_VGA_RESIZE_IN_PROGRESS if resize takes time and not yet finished.
+ * @param pInterface Pointer to this interface.
+ * @param cBits Color depth (bits per pixel) of the new video mode.
+ * @param pvVRAM Address of the guest VRAM.
+ * @param cbLine Size in bytes of a single scan line.
+ * @param cx New display width.
+ * @param cy New display height.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnResize,(PPDMIDISPLAYCONNECTOR pInterface, uint32_t cBits, void *pvVRAM, uint32_t cbLine, uint32_t cx, uint32_t cy));
+
+ /**
+ * Update a rectangle of the display.
+ * PDMIDISPLAYPORT::pfnUpdateDisplay is the caller.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param x The upper left corner x coordinate of the rectangle.
+ * @param y The upper left corner y coordinate of the rectangle.
+ * @param cx The width of the rectangle.
+ * @param cy The height of the rectangle.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdateRect,(PPDMIDISPLAYCONNECTOR pInterface, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy));
+
+ /**
+ * Refresh the display.
+ *
+ * The interval between these calls is set by
+ * PDMIDISPLAYPORT::pfnSetRefreshRate(). The driver should call
+ * PDMIDISPLAYPORT::pfnUpdateDisplay() if it wishes to refresh the
+ * display. PDMIDISPLAYPORT::pfnUpdateDisplay calls pfnUpdateRect with
+ * the changed rectangles.
+ *
+ * @param pInterface Pointer to this interface.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnRefresh,(PPDMIDISPLAYCONNECTOR pInterface));
+
+ /**
+ * Reset the display.
+ *
+ * Notification message when the graphics card has been reset.
+ *
+ * @param pInterface Pointer to this interface.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnReset,(PPDMIDISPLAYCONNECTOR pInterface));
+
+ /**
+ * LFB video mode enter/exit.
+ *
+ * Notification message when LinearFrameBuffer video mode is enabled/disabled.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param fEnabled false - LFB mode was disabled,
+ * true - an LFB mode was disabled
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnLFBModeChange, (PPDMIDISPLAYCONNECTOR pInterface, bool fEnabled));
+
+ /**
+ * Process the guest graphics adapter information.
+ *
+ * Direct notification from guest to the display connector.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pvVRAM Address of the guest VRAM.
+ * @param u32VRAMSize Size of the guest VRAM.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnProcessAdapterData, (PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, uint32_t u32VRAMSize));
+
+ /**
+ * Process the guest display information.
+ *
+ * Direct notification from guest to the display connector.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pvVRAM Address of the guest VRAM.
+ * @param uScreenId The index of the guest display to be processed.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnProcessDisplayData, (PPDMIDISPLAYCONNECTOR pInterface, void *pvVRAM, unsigned uScreenId));
+
+ /**
+ * Process the guest Video HW Acceleration command.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pCmd Video HW Acceleration Command to be processed.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVHWACommandProcess, (PPDMIDISPLAYCONNECTOR pInterface, PVBOXVHWACMD pCmd));
+
+ /**
+ * Process the guest chromium command.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pCmd Video HW Acceleration Command to be processed.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnCrHgsmiCommandProcess, (PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CMD pCmd, uint32_t cbCmd));
+
+ /**
+ * Process the guest chromium control command.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pCmd Video HW Acceleration Command to be processed.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnCrHgsmiControlProcess, (PPDMIDISPLAYCONNECTOR pInterface, PVBOXVDMACMD_CHROMIUM_CTL pCtl, uint32_t cbCtl));
+
+
+ /**
+ * The specified screen enters VBVA mode.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param uScreenId The screen updates are for.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVBVAEnable,(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, PVBVAHOSTFLAGS pHostFlags));
+
+ /**
+ * The specified screen leaves VBVA mode.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param uScreenId The screen updates are for.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVBVADisable,(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId));
+
+ /**
+ * A sequence of pfnVBVAUpdateProcess calls begins.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param uScreenId The screen updates are for.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVBVAUpdateBegin,(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId));
+
+ /**
+ * Process the guest VBVA command.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pCmd Video HW Acceleration Command to be processed.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVBVAUpdateProcess,(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, const PVBVACMDHDR pCmd, size_t cbCmd));
+
+ /**
+ * A sequence of pfnVBVAUpdateProcess calls ends.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param uScreenId The screen updates are for.
+ * @param x The upper left corner x coordinate of the combined rectangle of all VBVA updates.
+ * @param y The upper left corner y coordinate of the rectangle.
+ * @param cx The width of the rectangle.
+ * @param cy The height of the rectangle.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVBVAUpdateEnd,(PPDMIDISPLAYCONNECTOR pInterface, unsigned uScreenId, int32_t x, int32_t y, uint32_t cx, uint32_t cy));
+
+ /**
+ * Resize the display.
+ * This is called when the resolution changes. This usually happens on
+ * request from the guest os, but may also happen as the result of a reset.
+ * If the callback returns VINF_VGA_RESIZE_IN_PROGRESS, the caller (VGA device)
+ * must not access the connector and return.
+ *
+ * @todo Merge with pfnResize.
+ *
+ * @returns VINF_SUCCESS if the framebuffer resize was completed,
+ * VINF_VGA_RESIZE_IN_PROGRESS if resize takes time and not yet finished.
+ * @param pInterface Pointer to this interface.
+ * @param pView The description of VRAM block for this screen.
+ * @param pScreen The data of screen being resized.
+ * @param pvVRAM Address of the guest VRAM.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVBVAResize,(PPDMIDISPLAYCONNECTOR pInterface, const PVBVAINFOVIEW pView, const PVBVAINFOSCREEN pScreen, void *pvVRAM));
+
+ /**
+ * Update the pointer shape.
+ * This is called when the mouse pointer shape changes. The new shape
+ * is passed as a caller allocated buffer that will be freed after returning
+ *
+ * @param pInterface Pointer to this interface.
+ * @param fVisible Visibility indicator (if false, the other parameters are undefined).
+ * @param fAlpha Flag whether alpha channel is being passed.
+ * @param xHot Pointer hot spot x coordinate.
+ * @param yHot Pointer hot spot y coordinate.
+ * @param x Pointer new x coordinate on screen.
+ * @param y Pointer new y coordinate on screen.
+ * @param cx Pointer width in pixels.
+ * @param cy Pointer height in pixels.
+ * @param cbScanline Size of one scanline in bytes.
+ * @param pvShape New shape buffer.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVBVAMousePointerShape,(PPDMIDISPLAYCONNECTOR pInterface, bool fVisible, bool fAlpha,
+ uint32_t xHot, uint32_t yHot,
+ uint32_t cx, uint32_t cy,
+ const void *pvShape));
+
+ /** Read-only attributes.
+ * For preformance reasons some readonly attributes are kept in the interface.
+ * We trust the interface users to respect the readonlyness of these.
+ * @{
+ */
+ /** Pointer to the display data buffer. */
+ uint8_t *pu8Data;
+ /** Size of a scanline in the data buffer. */
+ uint32_t cbScanline;
+ /** The color depth (in bits) the graphics card is supposed to provide. */
+ uint32_t cBits;
+ /** The display width. */
+ uint32_t cx;
+ /** The display height. */
+ uint32_t cy;
+ /** @} */
+} PDMIDISPLAYCONNECTOR;
+/** PDMIDISPLAYCONNECTOR interface ID. */
+#define PDMIDISPLAYCONNECTOR_IID "c7a1b36d-8dfc-421d-b71f-3a0eeaf733e6"
+
+
+/** Pointer to a block port interface. */
+typedef struct PDMIBLOCKPORT *PPDMIBLOCKPORT;
+/**
+ * Block notify interface (down).
+ * Pair with PDMIBLOCK.
+ */
+typedef struct PDMIBLOCKPORT
+{
+ /**
+ * Returns the storage controller name, instance and LUN of the attached medium.
+ *
+ * @returns VBox status.
+ * @param pInterface Pointer to this interface.
+ * @param ppcszController Where to store the name of the storage controller.
+ * @param piInstance Where to store the instance number of the controller.
+ * @param piLUN Where to store the LUN of the attached device.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryDeviceLocation, (PPDMIBLOCKPORT pInterface, const char **ppcszController,
+ uint32_t *piInstance, uint32_t *piLUN));
+
+} PDMIBLOCKPORT;
+/** PDMIBLOCKPORT interface ID. */
+#define PDMIBLOCKPORT_IID "bbbed4cf-0862-4ffd-b60c-f7a65ef8e8ff"
+
+
+/**
+ * Callback which provides progress information.
+ *
+ * @return VBox status code.
+ * @param pvUser Opaque user data.
+ * @param uPercent Completion percentage.
+ */
+typedef DECLCALLBACK(int) FNSIMPLEPROGRESS(void *pvUser, unsigned uPercentage);
+/** Pointer to FNSIMPLEPROGRESS() */
+typedef FNSIMPLEPROGRESS *PFNSIMPLEPROGRESS;
+
+
+/**
+ * Block drive type.
+ */
+typedef enum PDMBLOCKTYPE
+{
+ /** Error (for the query function). */
+ PDMBLOCKTYPE_ERROR = 1,
+ /** 360KB 5 1/4" floppy drive. */
+ PDMBLOCKTYPE_FLOPPY_360,
+ /** 720KB 3 1/2" floppy drive. */
+ PDMBLOCKTYPE_FLOPPY_720,
+ /** 1.2MB 5 1/4" floppy drive. */
+ PDMBLOCKTYPE_FLOPPY_1_20,
+ /** 1.44MB 3 1/2" floppy drive. */
+ PDMBLOCKTYPE_FLOPPY_1_44,
+ /** 2.88MB 3 1/2" floppy drive. */
+ PDMBLOCKTYPE_FLOPPY_2_88,
+ /** CDROM drive. */
+ PDMBLOCKTYPE_CDROM,
+ /** DVD drive. */
+ PDMBLOCKTYPE_DVD,
+ /** Hard disk drive. */
+ PDMBLOCKTYPE_HARD_DISK
+} PDMBLOCKTYPE;
+
+
+/**
+ * Block raw command data transfer direction.
+ */
+typedef enum PDMBLOCKTXDIR
+{
+ PDMBLOCKTXDIR_NONE = 0,
+ PDMBLOCKTXDIR_FROM_DEVICE,
+ PDMBLOCKTXDIR_TO_DEVICE
+} PDMBLOCKTXDIR;
+
+
+/** Pointer to a block interface. */
+typedef struct PDMIBLOCK *PPDMIBLOCK;
+/**
+ * Block interface (up).
+ * Pair with PDMIBLOCKPORT.
+ */
+typedef struct PDMIBLOCK
+{
+ /**
+ * Read bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param off Offset to start reading from. The offset must be aligned to a sector boundary.
+ * @param pvBuf Where to store the read bits.
+ * @param cbRead Number of bytes to read. Must be aligned to a sector boundary.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRead,(PPDMIBLOCK pInterface, uint64_t off, void *pvBuf, size_t cbRead));
+
+ /**
+ * Write bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param off Offset to start writing at. The offset must be aligned to a sector boundary.
+ * @param pvBuf Where to store the write bits.
+ * @param cbWrite Number of bytes to write. Must be aligned to a sector boundary.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMIBLOCK pInterface, uint64_t off, const void *pvBuf, size_t cbWrite));
+
+ /**
+ * Make sure that the bits written are actually on the storage medium.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFlush,(PPDMIBLOCK pInterface));
+
+ /**
+ * Send a raw command to the underlying device (CDROM).
+ * This method is optional (i.e. the function pointer may be NULL).
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pbCmd Offset to start reading from.
+ * @param enmTxDir Direction of transfer.
+ * @param pvBuf Pointer tp the transfer buffer.
+ * @param cbBuf Size of the transfer buffer.
+ * @param pbSenseKey Status of the command (when return value is VERR_DEV_IO_ERROR).
+ * @param cTimeoutMillies Command timeout in milliseconds.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSendCmd,(PPDMIBLOCK pInterface, const uint8_t *pbCmd, PDMBLOCKTXDIR enmTxDir, void *pvBuf, uint32_t *pcbBuf, uint8_t *pabSense, size_t cbSense, uint32_t cTimeoutMillies));
+
+ /**
+ * Merge medium contents during a live snapshot deletion.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfnProgress Function pointer for progress notification.
+ * @param pvUser Opaque user data for progress notification.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMerge,(PPDMIBLOCK pInterface, PFNSIMPLEPROGRESS pfnProgress, void *pvUser));
+
+ /**
+ * Check if the media is readonly or not.
+ *
+ * @returns true if readonly.
+ * @returns false if read/write.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsReadOnly,(PPDMIBLOCK pInterface));
+
+ /**
+ * Gets the media size in bytes.
+ *
+ * @returns Media size in bytes.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize,(PPDMIBLOCK pInterface));
+
+ /**
+ * Gets the block drive type.
+ *
+ * @returns block drive type.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(PDMBLOCKTYPE, pfnGetType,(PPDMIBLOCK pInterface));
+
+ /**
+ * Gets the UUID of the block drive.
+ * Don't return the media UUID if it's removable.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pUuid Where to store the UUID on success.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetUuid,(PPDMIBLOCK pInterface, PRTUUID pUuid));
+
+ /**
+ * Discards the given range.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param paRanges Array of ranges to discard.
+ * @param cRanges Number of entries in the array.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDiscard,(PPDMIBLOCK pInterface, PCRTRANGE paRanges, unsigned cRanges));
+} PDMIBLOCK;
+/** PDMIBLOCK interface ID. */
+#define PDMIBLOCK_IID "5e7123dd-8cdf-4a6e-97a5-ab0c68d7e850"
+
+
+/** Pointer to a mount interface. */
+typedef struct PDMIMOUNTNOTIFY *PPDMIMOUNTNOTIFY;
+/**
+ * Block interface (up).
+ * Pair with PDMIMOUNT.
+ */
+typedef struct PDMIMOUNTNOTIFY
+{
+ /**
+ * Called when a media is mounted.
+ *
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnMountNotify,(PPDMIMOUNTNOTIFY pInterface));
+
+ /**
+ * Called when a media is unmounted
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUnmountNotify,(PPDMIMOUNTNOTIFY pInterface));
+} PDMIMOUNTNOTIFY;
+/** PDMIMOUNTNOTIFY interface ID. */
+#define PDMIMOUNTNOTIFY_IID "fa143ac9-9fc6-498e-997f-945380a558f9"
+
+
+/** Pointer to mount interface. */
+typedef struct PDMIMOUNT *PPDMIMOUNT;
+/**
+ * Mount interface (down).
+ * Pair with PDMIMOUNTNOTIFY.
+ */
+typedef struct PDMIMOUNT
+{
+ /**
+ * Mount a media.
+ *
+ * This will not unmount any currently mounted media!
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pszFilename Pointer to filename. If this is NULL it assumed that the caller have
+ * constructed a configuration which can be attached to the bottom driver.
+ * @param pszCoreDriver Core driver name. NULL will cause autodetection. Ignored if pszFilanem is NULL.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMount,(PPDMIMOUNT pInterface, const char *pszFilename, const char *pszCoreDriver));
+
+ /**
+ * Unmount the media.
+ *
+ * The driver will validate and pass it on. On the rebounce it will decide whether or not to detach it self.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread The emulation thread.
+ * @param fForce Force the unmount, even for locked media.
+ * @param fEject Eject the medium. Only relevant for host drives.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUnmount,(PPDMIMOUNT pInterface, bool fForce, bool fEject));
+
+ /**
+ * Checks if a media is mounted.
+ *
+ * @returns true if mounted.
+ * @returns false if not mounted.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsMounted,(PPDMIMOUNT pInterface));
+
+ /**
+ * Locks the media, preventing any unmounting of it.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLock,(PPDMIMOUNT pInterface));
+
+ /**
+ * Unlocks the media, canceling previous calls to pfnLock().
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUnlock,(PPDMIMOUNT pInterface));
+
+ /**
+ * Checks if a media is locked.
+ *
+ * @returns true if locked.
+ * @returns false if not locked.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsLocked,(PPDMIMOUNT pInterface));
+} PDMIMOUNT;
+/** PDMIMOUNT interface ID. */
+#define PDMIMOUNT_IID "34fc7a4c-623a-4806-a6bf-5be1be33c99f"
+
+
+/**
+ * Media geometry structure.
+ */
+typedef struct PDMMEDIAGEOMETRY
+{
+ /** Number of cylinders. */
+ uint32_t cCylinders;
+ /** Number of heads. */
+ uint32_t cHeads;
+ /** Number of sectors. */
+ uint32_t cSectors;
+} PDMMEDIAGEOMETRY;
+
+/** Pointer to media geometry structure. */
+typedef PDMMEDIAGEOMETRY *PPDMMEDIAGEOMETRY;
+/** Pointer to constant media geometry structure. */
+typedef const PDMMEDIAGEOMETRY *PCPDMMEDIAGEOMETRY;
+
+/** Pointer to a media port interface. */
+typedef struct PDMIMEDIAPORT *PPDMIMEDIAPORT;
+/**
+ * Media port interface (down).
+ */
+typedef struct PDMIMEDIAPORT
+{
+ /**
+ * Returns the storage controller name, instance and LUN of the attached medium.
+ *
+ * @returns VBox status.
+ * @param pInterface Pointer to this interface.
+ * @param ppcszController Where to store the name of the storage controller.
+ * @param piInstance Where to store the instance number of the controller.
+ * @param piLUN Where to store the LUN of the attached device.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryDeviceLocation, (PPDMIMEDIAPORT pInterface, const char **ppcszController,
+ uint32_t *piInstance, uint32_t *piLUN));
+
+} PDMIMEDIAPORT;
+/** PDMIMEDIAPORT interface ID. */
+#define PDMIMEDIAPORT_IID "9f7e8c9e-6d35-4453-bbef-1f78033174d6"
+
+/** Pointer to a media interface. */
+typedef struct PDMIMEDIA *PPDMIMEDIA;
+/**
+ * Media interface (up).
+ * Makes up the foundation for PDMIBLOCK and PDMIBLOCKBIOS.
+ * Pairs with PDMIMEDIAPORT.
+ */
+typedef struct PDMIMEDIA
+{
+ /**
+ * Read bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param off Offset to start reading from. The offset must be aligned to a sector boundary.
+ * @param pvBuf Where to store the read bits.
+ * @param cbRead Number of bytes to read. Must be aligned to a sector boundary.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRead,(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead));
+
+ /**
+ * Write bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param off Offset to start writing at. The offset must be aligned to a sector boundary.
+ * @param pvBuf Where to store the write bits.
+ * @param cbWrite Number of bytes to write. Must be aligned to a sector boundary.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMIMEDIA pInterface, uint64_t off, const void *pvBuf, size_t cbWrite));
+
+ /**
+ * Make sure that the bits written are actually on the storage medium.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFlush,(PPDMIMEDIA pInterface));
+
+ /**
+ * Merge medium contents during a live snapshot deletion. All details
+ * must have been configured through CFGM or this will fail.
+ * This method is optional (i.e. the function pointer may be NULL).
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfnProgress Function pointer for progress notification.
+ * @param pvUser Opaque user data for progress notification.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMerge,(PPDMIMEDIA pInterface, PFNSIMPLEPROGRESS pfnProgress, void *pvUser));
+
+ /**
+ * Get the media size in bytes.
+ *
+ * @returns Media size in bytes.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnGetSize,(PPDMIMEDIA pInterface));
+
+ /**
+ * Check if the media is readonly or not.
+ *
+ * @returns true if readonly.
+ * @returns false if read/write.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsReadOnly,(PPDMIMEDIA pInterface));
+
+ /**
+ * Get stored media geometry (physical CHS, PCHS) - BIOS property.
+ * This is an optional feature of a media.
+ *
+ * @returns VBox status code.
+ * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry.
+ * @returns VERR_PDM_GEOMETRY_NOT_SET if the geometry hasn't been set using pfnBiosSetPCHSGeometry() yet.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pPCHSGeometry Pointer to PCHS geometry (cylinders/heads/sectors).
+ * @remark This has no influence on the read/write operations.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnBiosGetPCHSGeometry,(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry));
+
+ /**
+ * Store the media geometry (physical CHS, PCHS) - BIOS property.
+ * This is an optional feature of a media.
+ *
+ * @returns VBox status code.
+ * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pPCHSGeometry Pointer to PCHS geometry (cylinders/heads/sectors).
+ * @remark This has no influence on the read/write operations.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnBiosSetPCHSGeometry,(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry));
+
+ /**
+ * Get stored media geometry (logical CHS, LCHS) - BIOS property.
+ * This is an optional feature of a media.
+ *
+ * @returns VBox status code.
+ * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry.
+ * @returns VERR_PDM_GEOMETRY_NOT_SET if the geometry hasn't been set using pfnBiosSetLCHSGeometry() yet.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pLCHSGeometry Pointer to LCHS geometry (cylinders/heads/sectors).
+ * @remark This has no influence on the read/write operations.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnBiosGetLCHSGeometry,(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry));
+
+ /**
+ * Store the media geometry (logical CHS, LCHS) - BIOS property.
+ * This is an optional feature of a media.
+ *
+ * @returns VBox status code.
+ * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pLCHSGeometry Pointer to LCHS geometry (cylinders/heads/sectors).
+ * @remark This has no influence on the read/write operations.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnBiosSetLCHSGeometry,(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry));
+
+ /**
+ * Gets the UUID of the media drive.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pUuid Where to store the UUID on success.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetUuid,(PPDMIMEDIA pInterface, PRTUUID pUuid));
+
+ /**
+ * Discards the given range.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param paRanges Array of ranges to discard.
+ * @param cRanges Number of entries in the array.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDiscard,(PPDMIMEDIA pInterface, PCRTRANGE paRanges, unsigned cRanges));
+
+} PDMIMEDIA;
+/** PDMIMEDIA interface ID. */
+#define PDMIMEDIA_IID "ec385d21-7aa9-42ca-8cfb-e1388297fa52"
+
+
+/** Pointer to a block BIOS interface. */
+typedef struct PDMIBLOCKBIOS *PPDMIBLOCKBIOS;
+/**
+ * Media BIOS interface (Up / External).
+ * The interface the getting and setting properties which the BIOS/CMOS care about.
+ */
+typedef struct PDMIBLOCKBIOS
+{
+ /**
+ * Get stored media geometry (physical CHS, PCHS) - BIOS property.
+ * This is an optional feature of a media.
+ *
+ * @returns VBox status code.
+ * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry.
+ * @returns VERR_PDM_GEOMETRY_NOT_SET if the geometry hasn't been set using pfnSetPCHSGeometry() yet.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pPCHSGeometry Pointer to PCHS geometry (cylinders/heads/sectors).
+ * @remark This has no influence on the read/write operations.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetPCHSGeometry,(PPDMIBLOCKBIOS pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry));
+
+ /**
+ * Store the media geometry (physical CHS, PCHS) - BIOS property.
+ * This is an optional feature of a media.
+ *
+ * @returns VBox status code.
+ * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pPCHSGeometry Pointer to PCHS geometry (cylinders/heads/sectors).
+ * @remark This has no influence on the read/write operations.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetPCHSGeometry,(PPDMIBLOCKBIOS pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry));
+
+ /**
+ * Get stored media geometry (logical CHS, LCHS) - BIOS property.
+ * This is an optional feature of a media.
+ *
+ * @returns VBox status code.
+ * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry.
+ * @returns VERR_PDM_GEOMETRY_NOT_SET if the geometry hasn't been set using pfnSetLCHSGeometry() yet.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pLCHSGeometry Pointer to LCHS geometry (cylinders/heads/sectors).
+ * @remark This has no influence on the read/write operations.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetLCHSGeometry,(PPDMIBLOCKBIOS pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry));
+
+ /**
+ * Store the media geometry (logical CHS, LCHS) - BIOS property.
+ * This is an optional feature of a media.
+ *
+ * @returns VBox status code.
+ * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pLCHSGeometry Pointer to LCHS geometry (cylinders/heads/sectors).
+ * @remark This has no influence on the read/write operations.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetLCHSGeometry,(PPDMIBLOCKBIOS pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry));
+
+ /**
+ * Checks if the device should be visible to the BIOS or not.
+ *
+ * @returns true if the device is visible to the BIOS.
+ * @returns false if the device is not visible to the BIOS.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnIsVisible,(PPDMIBLOCKBIOS pInterface));
+
+ /**
+ * Gets the block drive type.
+ *
+ * @returns block drive type.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(PDMBLOCKTYPE, pfnGetType,(PPDMIBLOCKBIOS pInterface));
+
+} PDMIBLOCKBIOS;
+/** PDMIBLOCKBIOS interface ID. */
+#define PDMIBLOCKBIOS_IID "477c3eee-a48d-48a9-82fd-2a54de16b2e9"
+
+
+/** Pointer to a static block core driver interface. */
+typedef struct PDMIMEDIASTATIC *PPDMIMEDIASTATIC;
+/**
+ * Static block core driver interface.
+ */
+typedef struct PDMIMEDIASTATIC
+{
+ /**
+ * Check if the specified file is a format which the core driver can handle.
+ *
+ * @returns true / false accordingly.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pszFilename Name of the file to probe.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnCanHandle,(PPDMIMEDIASTATIC pInterface, const char *pszFilename));
+} PDMIMEDIASTATIC;
+
+
+
+
+
+/** Pointer to an asynchronous block notify interface. */
+typedef struct PDMIBLOCKASYNCPORT *PPDMIBLOCKASYNCPORT;
+/**
+ * Asynchronous block notify interface (up).
+ * Pair with PDMIBLOCKASYNC.
+ */
+typedef struct PDMIBLOCKASYNCPORT
+{
+ /**
+ * Notify completion of an asynchronous transfer.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvUser The user argument given in pfnStartWrite/Read.
+ * @param rcReq IPRT Status code of the completed request.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTransferCompleteNotify, (PPDMIBLOCKASYNCPORT pInterface, void *pvUser, int rcReq));
+} PDMIBLOCKASYNCPORT;
+/** PDMIBLOCKASYNCPORT interface ID. */
+#define PDMIBLOCKASYNCPORT_IID "e3bdc0cb-9d99-41dd-8eec-0dc8cf5b2a92"
+
+
+
+/** Pointer to an asynchronous block interface. */
+typedef struct PDMIBLOCKASYNC *PPDMIBLOCKASYNC;
+/**
+ * Asynchronous block interface (down).
+ * Pair with PDMIBLOCKASYNCPORT.
+ */
+typedef struct PDMIBLOCKASYNC
+{
+ /**
+ * Start reading task.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param off Offset to start reading from.c
+ * @param paSegs Pointer to the S/G segment array.
+ * @param cSegs Number of entries in the array.
+ * @param cbRead Number of bytes to read. Must be aligned to a sector boundary.
+ * @param pvUser User argument which is returned in completion callback.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStartRead,(PPDMIBLOCKASYNC pInterface, uint64_t off, PCRTSGSEG paSegs, unsigned cSegs, size_t cbRead, void *pvUser));
+
+ /**
+ * Write bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param off Offset to start writing at. The offset must be aligned to a sector boundary.
+ * @param paSegs Pointer to the S/G segment array.
+ * @param cSegs Number of entries in the array.
+ * @param cbWrite Number of bytes to write. Must be aligned to a sector boundary.
+ * @param pvUser User argument which is returned in completion callback.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStartWrite,(PPDMIBLOCKASYNC pInterface, uint64_t off, PCRTSGSEG paSegs, unsigned cSegs, size_t cbWrite, void *pvUser));
+
+ /**
+ * Flush everything to disk.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvUser User argument which is returned in completion callback.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStartFlush,(PPDMIBLOCKASYNC pInterface, void *pvUser));
+
+ /**
+ * Discards the given range.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param paRanges Array of ranges to discard.
+ * @param cRanges Number of entries in the array.
+ * @param pvUser User argument which is returned in completion callback.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStartDiscard,(PPDMIBLOCKASYNC pInterface, PCRTRANGE paRanges, unsigned cRanges, void *pvUser));
+
+} PDMIBLOCKASYNC;
+/** PDMIBLOCKASYNC interface ID. */
+#define PDMIBLOCKASYNC_IID "a921dd96-1748-4ecd-941e-d5f3cd4c8fe4"
+
+
+/** Pointer to an asynchronous notification interface. */
+typedef struct PDMIMEDIAASYNCPORT *PPDMIMEDIAASYNCPORT;
+/**
+ * Asynchronous version of the media interface (up).
+ * Pair with PDMIMEDIAASYNC.
+ */
+typedef struct PDMIMEDIAASYNCPORT
+{
+ /**
+ * Notify completion of a task.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvUser The user argument given in pfnStartWrite.
+ * @param rcReq IPRT Status code of the completed request.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTransferCompleteNotify, (PPDMIMEDIAASYNCPORT pInterface, void *pvUser, int rcReq));
+} PDMIMEDIAASYNCPORT;
+/** PDMIMEDIAASYNCPORT interface ID. */
+#define PDMIMEDIAASYNCPORT_IID "22d38853-901f-4a71-9670-4d9da6e82317"
+
+
+/** Pointer to an asynchronous media interface. */
+typedef struct PDMIMEDIAASYNC *PPDMIMEDIAASYNC;
+/**
+ * Asynchronous version of PDMIMEDIA (down).
+ * Pair with PDMIMEDIAASYNCPORT.
+ */
+typedef struct PDMIMEDIAASYNC
+{
+ /**
+ * Start reading task.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param off Offset to start reading from. Must be aligned to a sector boundary.
+ * @param paSegs Pointer to the S/G segment array.
+ * @param cSegs Number of entries in the array.
+ * @param cbRead Number of bytes to read. Must be aligned to a sector boundary.
+ * @param pvUser User data.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStartRead,(PPDMIMEDIAASYNC pInterface, uint64_t off, PCRTSGSEG paSegs, unsigned cSegs, size_t cbRead, void *pvUser));
+
+ /**
+ * Start writing task.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param off Offset to start writing at. Must be aligned to a sector boundary.
+ * @param paSegs Pointer to the S/G segment array.
+ * @param cSegs Number of entries in the array.
+ * @param cbWrite Number of bytes to write. Must be aligned to a sector boundary.
+ * @param pvUser User data.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStartWrite,(PPDMIMEDIAASYNC pInterface, uint64_t off, PCRTSGSEG paSegs, unsigned cSegs, size_t cbWrite, void *pvUser));
+
+ /**
+ * Flush everything to disk.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvUser User argument which is returned in completion callback.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStartFlush,(PPDMIMEDIAASYNC pInterface, void *pvUser));
+
+ /**
+ * Discards the given range.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param paRanges Array of ranges to discard.
+ * @param cRanges Number of entries in the array.
+ * @param pvUser User argument which is returned in completion callback.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStartDiscard,(PPDMIMEDIAASYNC pInterface, PCRTRANGE paRanges, unsigned cRanges, void *pvUser));
+
+} PDMIMEDIAASYNC;
+/** PDMIMEDIAASYNC interface ID. */
+#define PDMIMEDIAASYNC_IID "4be209d3-ccb5-4297-82fe-7d8018bc6ab4"
+
+
+/** Pointer to a char port interface. */
+typedef struct PDMICHARPORT *PPDMICHARPORT;
+/**
+ * Char port interface (down).
+ * Pair with PDMICHARCONNECTOR.
+ */
+typedef struct PDMICHARPORT
+{
+ /**
+ * Deliver data read to the device/driver.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf Where the read bits are stored.
+ * @param pcbRead Number of bytes available for reading/having been read.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnNotifyRead,(PPDMICHARPORT pInterface, const void *pvBuf, size_t *pcbRead));
+
+ /**
+ * Notify the device/driver when the status lines changed.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fNewStatusLine New state of the status line pins.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnNotifyStatusLinesChanged,(PPDMICHARPORT pInterface, uint32_t fNewStatusLines));
+
+ /**
+ * Notify the device when the driver buffer is full.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fFull Buffer full.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnNotifyBufferFull,(PPDMICHARPORT pInterface, bool fFull));
+
+ /**
+ * Notify the device/driver that a break occurred.
+ *
+ * @returns VBox statsus code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnNotifyBreak,(PPDMICHARPORT pInterface));
+} PDMICHARPORT;
+/** PDMICHARPORT interface ID. */
+#define PDMICHARPORT_IID "22769834-ea8b-4a6d-ade1-213dcdbd1228"
+
+/** @name Bit mask definitions for status line type.
+ * @{ */
+#define PDMICHARPORT_STATUS_LINES_DCD RT_BIT(0)
+#define PDMICHARPORT_STATUS_LINES_RI RT_BIT(1)
+#define PDMICHARPORT_STATUS_LINES_DSR RT_BIT(2)
+#define PDMICHARPORT_STATUS_LINES_CTS RT_BIT(3)
+/** @} */
+
+
+/** Pointer to a char interface. */
+typedef struct PDMICHARCONNECTOR *PPDMICHARCONNECTOR;
+/**
+ * Char connector interface (up).
+ * Pair with PDMICHARPORT.
+ */
+typedef struct PDMICHARCONNECTOR
+{
+ /**
+ * Write bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf Where to store the write bits.
+ * @param cbWrite Number of bytes to write.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMICHARCONNECTOR pInterface, const void *pvBuf, size_t cbWrite));
+
+ /**
+ * Set device parameters.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param Bps Speed of the serial connection. (bits per second)
+ * @param chParity Parity method: 'E' - even, 'O' - odd, 'N' - none.
+ * @param cDataBits Number of data bits.
+ * @param cStopBits Number of stop bits.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetParameters,(PPDMICHARCONNECTOR pInterface, unsigned Bps, char chParity, unsigned cDataBits, unsigned cStopBits));
+
+ /**
+ * Set the state of the modem lines.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fRequestToSend Set to true to make the Request to Send line active otherwise to 0.
+ * @param fDataTerminalReady Set to true to make the Data Terminal Ready line active otherwise 0.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetModemLines,(PPDMICHARCONNECTOR pInterface, bool fRequestToSend, bool fDataTerminalReady));
+
+ /**
+ * Sets the TD line into break condition.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fBreak Set to true to let the device send a break false to put into normal operation.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetBreak,(PPDMICHARCONNECTOR pInterface, bool fBreak));
+} PDMICHARCONNECTOR;
+/** PDMICHARCONNECTOR interface ID. */
+#define PDMICHARCONNECTOR_IID "4ad5c190-b408-4cef-926f-fbffce0dc5cc"
+
+
+/** Pointer to a stream interface. */
+typedef struct PDMISTREAM *PPDMISTREAM;
+/**
+ * Stream interface (up).
+ * Makes up the foundation for PDMICHARCONNECTOR. No pair interface.
+ */
+typedef struct PDMISTREAM
+{
+ /**
+ * Read bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf Where to store the read bits.
+ * @param cbRead Number of bytes to read/bytes actually read.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRead,(PPDMISTREAM pInterface, void *pvBuf, size_t *cbRead));
+
+ /**
+ * Write bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf Where to store the write bits.
+ * @param cbWrite Number of bytes to write/bytes actually written.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMISTREAM pInterface, const void *pvBuf, size_t *cbWrite));
+} PDMISTREAM;
+/** PDMISTREAM interface ID. */
+#define PDMISTREAM_IID "d1a5bf5e-3d2c-449a-bde9-addd7920b71f"
+
+
+/** Mode of the parallel port */
+typedef enum PDMPARALLELPORTMODE
+{
+ /** First invalid mode. */
+ PDM_PARALLEL_PORT_MODE_INVALID = 0,
+ /** SPP (Compatibility mode). */
+ PDM_PARALLEL_PORT_MODE_SPP,
+ /** EPP Data mode. */
+ PDM_PARALLEL_PORT_MODE_EPP_DATA,
+ /** EPP Address mode. */
+ PDM_PARALLEL_PORT_MODE_EPP_ADDR,
+ /** ECP mode (not implemented yet). */
+ PDM_PARALLEL_PORT_MODE_ECP,
+ /** 32bit hack. */
+ PDM_PARALLEL_PORT_MODE_32BIT_HACK = 0x7fffffff
+} PDMPARALLELPORTMODE;
+
+/** Pointer to a host parallel port interface. */
+typedef struct PDMIHOSTPARALLELPORT *PPDMIHOSTPARALLELPORT;
+/**
+ * Host parallel port interface (down).
+ * Pair with PDMIHOSTPARALLELCONNECTOR.
+ */
+typedef struct PDMIHOSTPARALLELPORT
+{
+ /**
+ * Notify device/driver that an interrupt has occurred.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnNotifyInterrupt,(PPDMIHOSTPARALLELPORT pInterface));
+} PDMIHOSTPARALLELPORT;
+/** PDMIHOSTPARALLELPORT interface ID. */
+#define PDMIHOSTPARALLELPORT_IID "f24b8668-e7f6-4eaa-a14c-4aa2a5f7048e"
+
+
+
+/** Pointer to a Host Parallel connector interface. */
+typedef struct PDMIHOSTPARALLELCONNECTOR *PPDMIHOSTPARALLELCONNECTOR;
+/**
+ * Host parallel connector interface (up).
+ * Pair with PDMIHOSTPARALLELPORT.
+ */
+typedef struct PDMIHOSTPARALLELCONNECTOR
+{
+ /**
+ * Write bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf Where to store the write bits.
+ * @param cbWrite Number of bytes to write.
+ * @param enmMode Mode to write the data.
+ * @thread Any thread.
+ * @todo r=klaus cbWrite only defines buffer length, method needs a way top return actually written amount of data.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWrite,(PPDMIHOSTPARALLELCONNECTOR pInterface, const void *pvBuf,
+ size_t cbWrite, PDMPARALLELPORTMODE enmMode));
+
+ /**
+ * Read bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf Where to store the read bits.
+ * @param cbRead Number of bytes to read.
+ * @param enmMode Mode to read the data.
+ * @thread Any thread.
+ * @todo r=klaus cbRead only defines buffer length, method needs a way top return actually read amount of data.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRead,(PPDMIHOSTPARALLELCONNECTOR pInterface, void *pvBuf,
+ size_t cbRead, PDMPARALLELPORTMODE enmMode));
+
+ /**
+ * Set data direction of the port (forward/reverse).
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fForward Flag whether to indicate whether the port is operated in forward or reverse mode.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetPortDirection,(PPDMIHOSTPARALLELCONNECTOR pInterface, bool fForward));
+
+ /**
+ * Write control register bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fReg The new control register value.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWriteControl,(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t fReg));
+
+ /**
+ * Read control register bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfReg Where to store the control register bits.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReadControl,(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t *pfReg));
+
+ /**
+ * Read status register bits.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfReg Where to store the status register bits.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReadStatus,(PPDMIHOSTPARALLELCONNECTOR pInterface, uint8_t *pfReg));
+
+} PDMIHOSTPARALLELCONNECTOR;
+/** PDMIHOSTPARALLELCONNECTOR interface ID. */
+#define PDMIHOSTPARALLELCONNECTOR_IID "7c532602-7438-4fbc-9265-349d9f0415f9"
+
+
+/** ACPI power source identifier */
+typedef enum PDMACPIPOWERSOURCE
+{
+ PDM_ACPI_POWER_SOURCE_UNKNOWN = 0,
+ PDM_ACPI_POWER_SOURCE_OUTLET,
+ PDM_ACPI_POWER_SOURCE_BATTERY
+} PDMACPIPOWERSOURCE;
+/** Pointer to ACPI battery state. */
+typedef PDMACPIPOWERSOURCE *PPDMACPIPOWERSOURCE;
+
+/** ACPI battey capacity */
+typedef enum PDMACPIBATCAPACITY
+{
+ PDM_ACPI_BAT_CAPACITY_MIN = 0,
+ PDM_ACPI_BAT_CAPACITY_MAX = 100,
+ PDM_ACPI_BAT_CAPACITY_UNKNOWN = 255
+} PDMACPIBATCAPACITY;
+/** Pointer to ACPI battery capacity. */
+typedef PDMACPIBATCAPACITY *PPDMACPIBATCAPACITY;
+
+/** ACPI battery state. See ACPI 3.0 spec '_BST (Battery Status)' */
+typedef enum PDMACPIBATSTATE
+{
+ PDM_ACPI_BAT_STATE_CHARGED = 0x00,
+ PDM_ACPI_BAT_STATE_DISCHARGING = 0x01,
+ PDM_ACPI_BAT_STATE_CHARGING = 0x02,
+ PDM_ACPI_BAT_STATE_CRITICAL = 0x04
+} PDMACPIBATSTATE;
+/** Pointer to ACPI battery state. */
+typedef PDMACPIBATSTATE *PPDMACPIBATSTATE;
+
+/** Pointer to an ACPI port interface. */
+typedef struct PDMIACPIPORT *PPDMIACPIPORT;
+/**
+ * ACPI port interface (down). Used by both the ACPI driver and (grumble) main.
+ * Pair with PDMIACPICONNECTOR.
+ */
+typedef struct PDMIACPIPORT
+{
+ /**
+ * Send an ACPI power off event.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPowerButtonPress,(PPDMIACPIPORT pInterface));
+
+ /**
+ * Send an ACPI sleep button event.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSleepButtonPress,(PPDMIACPIPORT pInterface));
+
+ /**
+ * Check if the last power button event was handled by the guest.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfHandled Is set to true if the last power button event was handled, false otherwise.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetPowerButtonHandled,(PPDMIACPIPORT pInterface, bool *pfHandled));
+
+ /**
+ * Check if the guest entered the ACPI mode.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfEnabled Is set to true if the guest entered the ACPI mode, false otherwise.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetGuestEnteredACPIMode,(PPDMIACPIPORT pInterface, bool *pfEntered));
+
+ /**
+ * Check if the given CPU is still locked by the guest.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param uCpu The CPU to check for.
+ * @param pfLocked Is set to true if the CPU is still locked by the guest, false otherwise.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetCpuStatus,(PPDMIACPIPORT pInterface, unsigned uCpu, bool *pfLocked));
+} PDMIACPIPORT;
+/** PDMIACPIPORT interface ID. */
+#define PDMIACPIPORT_IID "30d3dc4c-6a73-40c8-80e9-34309deacbb3"
+
+
+/** Pointer to an ACPI connector interface. */
+typedef struct PDMIACPICONNECTOR *PPDMIACPICONNECTOR;
+/**
+ * ACPI connector interface (up).
+ * Pair with PDMIACPIPORT.
+ */
+typedef struct PDMIACPICONNECTOR
+{
+ /**
+ * Get the current power source of the host system.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param penmPowerSource Pointer to the power source result variable.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryPowerSource,(PPDMIACPICONNECTOR, PPDMACPIPOWERSOURCE penmPowerSource));
+
+ /**
+ * Query the current battery status of the host system.
+ *
+ * @returns VBox status code?
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfPresent Is set to true if battery is present, false otherwise.
+ * @param penmRemainingCapacity Pointer to the battery remaining capacity (0 - 100 or 255 for unknown).
+ * @param penmBatteryState Pointer to the battery status.
+ * @param pu32PresentRate Pointer to the present rate (0..1000 of the total capacity).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryBatteryStatus,(PPDMIACPICONNECTOR, bool *pfPresent, PPDMACPIBATCAPACITY penmRemainingCapacity,
+ PPDMACPIBATSTATE penmBatteryState, uint32_t *pu32PresentRate));
+} PDMIACPICONNECTOR;
+/** PDMIACPICONNECTOR interface ID. */
+#define PDMIACPICONNECTOR_IID "5f14bf8d-1edf-4e3a-a1e1-cca9fd08e359"
+
+
+/** Pointer to a VMMDevice port interface. */
+typedef struct PDMIVMMDEVPORT *PPDMIVMMDEVPORT;
+/**
+ * VMMDevice port interface (down).
+ * Pair with PDMIVMMDEVCONNECTOR.
+ */
+typedef struct PDMIVMMDEVPORT
+{
+ /**
+ * Return the current absolute mouse position in pixels
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pxAbs Pointer of result value, can be NULL
+ * @param pyAbs Pointer of result value, can be NULL
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryAbsoluteMouse,(PPDMIVMMDEVPORT pInterface, int32_t *pxAbs, int32_t *pyAbs));
+
+ /**
+ * Set the new absolute mouse position in pixels
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param xabs New absolute X position
+ * @param yAbs New absolute Y position
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetAbsoluteMouse,(PPDMIVMMDEVPORT pInterface, int32_t xAbs, int32_t yAbs));
+
+ /**
+ * Return the current mouse capability flags
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pfCapabilities Pointer of result value
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryMouseCapabilities,(PPDMIVMMDEVPORT pInterface, uint32_t *pfCapabilities));
+
+ /**
+ * Set the current mouse capability flag (host side)
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fCapsAdded Mask of capabilities to add to the flag
+ * @param fCapsRemoved Mask of capabilities to remove from the flag
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUpdateMouseCapabilities,(PPDMIVMMDEVPORT pInterface, uint32_t fCapsAdded, uint32_t fCapsRemoved));
+
+ /**
+ * Issue a display resolution change request.
+ *
+ * Note that there can only one request in the queue and that in case the guest does
+ * not process it, issuing another request will overwrite the previous.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param cx Horizontal pixel resolution (0 = do not change).
+ * @param cy Vertical pixel resolution (0 = do not change).
+ * @param cBits Bits per pixel (0 = do not change).
+ * @param idxDisplay The display index.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRequestDisplayChange,(PPDMIVMMDEVPORT pInterface, uint32_t cx, uint32_t cy, uint32_t cBits, uint32_t idxDisplay));
+
+ /**
+ * Pass credentials to guest.
+ *
+ * Note that there can only be one set of credentials and the guest may or may not
+ * query them and may do whatever it wants with them.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pszUsername User name, may be empty (UTF-8).
+ * @param pszPassword Password, may be empty (UTF-8).
+ * @param pszDomain Domain name, may be empty (UTF-8).
+ * @param fFlags VMMDEV_SETCREDENTIALS_*.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetCredentials,(PPDMIVMMDEVPORT pInterface, const char *pszUsername,
+ const char *pszPassword, const char *pszDomain,
+ uint32_t fFlags));
+
+ /**
+ * Notify the driver about a VBVA status change.
+ *
+ * @returns Nothing. Because it is informational callback.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fEnabled Current VBVA status.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVBVAChange, (PPDMIVMMDEVPORT pInterface, bool fEnabled));
+
+ /**
+ * Issue a seamless mode change request.
+ *
+ * Note that there can only one request in the queue and that in case the guest does
+ * not process it, issuing another request will overwrite the previous.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fEnabled Seamless mode enabled or not
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRequestSeamlessChange,(PPDMIVMMDEVPORT pInterface, bool fEnabled));
+
+ /**
+ * Issue a memory balloon change request.
+ *
+ * Note that there can only one request in the queue and that in case the guest does
+ * not process it, issuing another request will overwrite the previous.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param cMbBalloon Balloon size in megabytes
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetMemoryBalloon,(PPDMIVMMDEVPORT pInterface, uint32_t cMbBalloon));
+
+ /**
+ * Issue a statistcs interval change request.
+ *
+ * Note that there can only one request in the queue and that in case the guest does
+ * not process it, issuing another request will overwrite the previous.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param cSecsStatInterval Statistics query interval in seconds
+ * (0=disable).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetStatisticsInterval,(PPDMIVMMDEVPORT pInterface, uint32_t cSecsStatInterval));
+
+ /**
+ * Notify the guest about a VRDP status change.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fVRDPEnabled Current VRDP status.
+ * @param uVRDPExperienceLevel Which visual effects to be disabled in
+ * the guest.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVRDPChange, (PPDMIVMMDEVPORT pInterface, bool fVRDPEnabled, uint32_t uVRDPExperienceLevel));
+
+ /**
+ * Notify the guest of CPU hot-unplug event.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param idCpuCore The core id of the CPU to remove.
+ * @param idCpuPackage The package id of the CPU to remove.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCpuHotUnplug, (PPDMIVMMDEVPORT pInterface, uint32_t idCpuCore, uint32_t idCpuPackage));
+
+ /**
+ * Notify the guest of CPU hot-plug event.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param idCpuCore The core id of the CPU to add.
+ * @param idCpuPackage The package id of the CPU to add.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCpuHotPlug, (PPDMIVMMDEVPORT pInterface, uint32_t idCpuCore, uint32_t idCpuPackage));
+
+} PDMIVMMDEVPORT;
+/** PDMIVMMDEVPORT interface ID. */
+#define PDMIVMMDEVPORT_IID "d7e52035-3b6c-422e-9215-2a75646a945d"
+
+
+/** Pointer to a HPET legacy notification interface. */
+typedef struct PDMIHPETLEGACYNOTIFY *PPDMIHPETLEGACYNOTIFY;
+/**
+ * HPET legacy notification interface.
+ */
+typedef struct PDMIHPETLEGACYNOTIFY
+{
+ /**
+ * Notify about change of HPET legacy mode.
+ *
+ * @param pInterface Pointer to the interface structure containing the
+ * called function pointer.
+ * @param fActivated If HPET legacy mode is activated (@c true) or
+ * deactivated (@c false).
+ */
+ DECLR3CALLBACKMEMBER(void, pfnModeChanged,(PPDMIHPETLEGACYNOTIFY pInterface, bool fActivated));
+} PDMIHPETLEGACYNOTIFY;
+/** PDMIHPETLEGACYNOTIFY interface ID. */
+#define PDMIHPETLEGACYNOTIFY_IID "c9ada595-4b65-4311-8b21-b10498997774"
+
+
+/** @name Flags for PDMIVMMDEVPORT::pfnSetCredentials.
+ * @{ */
+/** The guest should perform a logon with the credentials. */
+#define VMMDEV_SETCREDENTIALS_GUESTLOGON RT_BIT(0)
+/** The guest should prevent local logons. */
+#define VMMDEV_SETCREDENTIALS_NOLOCALLOGON RT_BIT(1)
+/** The guest should verify the credentials. */
+#define VMMDEV_SETCREDENTIALS_JUDGE RT_BIT(15)
+/** @} */
+
+/** Forward declaration of the guest information structure. */
+struct VBoxGuestInfo;
+/** Forward declaration of the guest information-2 structure. */
+struct VBoxGuestInfo2;
+/** Forward declaration of the guest statistics structure */
+struct VBoxGuestStatistics;
+/** Forward declaration of the guest status structure */
+struct VBoxGuestStatus;
+
+/** Forward declaration of the video accelerator command memory. */
+struct VBVAMEMORY;
+/** Pointer to video accelerator command memory. */
+typedef struct VBVAMEMORY *PVBVAMEMORY;
+
+/** Pointer to a VMMDev connector interface. */
+typedef struct PDMIVMMDEVCONNECTOR *PPDMIVMMDEVCONNECTOR;
+/**
+ * VMMDev connector interface (up).
+ * Pair with PDMIVMMDEVPORT.
+ */
+typedef struct PDMIVMMDEVCONNECTOR
+{
+ /**
+ * Update guest facility status.
+ *
+ * Called in response to VMMDevReq_ReportGuestStatus, reset or state restore.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param uFacility The facility.
+ * @param uStatus The status.
+ * @param fFlags Flags assoicated with the update. Currently
+ * reserved and should be ignored.
+ * @param pTimeSpecTS Pointer to the timestamp of this report.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdateGuestStatus,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t uFacility, uint16_t uStatus,
+ uint32_t fFlags, PCRTTIMESPEC pTimeSpecTS));
+
+ /**
+ * Reports the guest API and OS version.
+ * Called whenever the Additions issue a guest info report request.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pGuestInfo Pointer to guest information structure
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdateGuestInfo,(PPDMIVMMDEVCONNECTOR pInterface, const struct VBoxGuestInfo *pGuestInfo));
+
+ /**
+ * Reports the detailed Guest Additions version.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param uFullVersion The guest additions version as a full version.
+ * Use VBOX_FULL_VERSION_GET_MAJOR,
+ * VBOX_FULL_VERSION_GET_MINOR and
+ * VBOX_FULL_VERSION_GET_BUILD to access it.
+ * (This will not be zero, so turn down the
+ * paranoia level a notch.)
+ * @param pszName Pointer to the sanitized version name. This can
+ * be empty, but will not be NULL. If not empty,
+ * it will contain a build type tag and/or a
+ * publisher tag. If both, then they are separated
+ * by an underscore (VBOX_VERSION_STRING fashion).
+ * @param uRevision The SVN revision. Can be 0.
+ * @param fFeatures Feature mask, currently none are defined.
+ *
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdateGuestInfo2,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t uFullVersion,
+ const char *pszName, uint32_t uRevision, uint32_t fFeatures));
+
+ /**
+ * Update the guest additions capabilities.
+ * This is called when the guest additions capabilities change. The new capabilities
+ * are given and the connector should update its internal state.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param newCapabilities New capabilities.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdateGuestCapabilities,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t newCapabilities));
+
+ /**
+ * Update the mouse capabilities.
+ * This is called when the mouse capabilities change. The new capabilities
+ * are given and the connector should update its internal state.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param newCapabilities New capabilities.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdateMouseCapabilities,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t newCapabilities));
+
+ /**
+ * Update the pointer shape.
+ * This is called when the mouse pointer shape changes. The new shape
+ * is passed as a caller allocated buffer that will be freed after returning
+ *
+ * @param pInterface Pointer to this interface.
+ * @param fVisible Visibility indicator (if false, the other parameters are undefined).
+ * @param fAlpha Flag whether alpha channel is being passed.
+ * @param xHot Pointer hot spot x coordinate.
+ * @param yHot Pointer hot spot y coordinate.
+ * @param x Pointer new x coordinate on screen.
+ * @param y Pointer new y coordinate on screen.
+ * @param cx Pointer width in pixels.
+ * @param cy Pointer height in pixels.
+ * @param cbScanline Size of one scanline in bytes.
+ * @param pvShape New shape buffer.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUpdatePointerShape,(PPDMIVMMDEVCONNECTOR pInterface, bool fVisible, bool fAlpha,
+ uint32_t xHot, uint32_t yHot,
+ uint32_t cx, uint32_t cy,
+ void *pvShape));
+
+ /**
+ * Enable or disable video acceleration on behalf of guest.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param fEnable Whether to enable acceleration.
+ * @param pVbvaMemory Video accelerator memory.
+
+ * @return VBox rc. VINF_SUCCESS if VBVA was enabled.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVideoAccelEnable,(PPDMIVMMDEVCONNECTOR pInterface, bool fEnable, PVBVAMEMORY pVbvaMemory));
+
+ /**
+ * Force video queue processing.
+ *
+ * @param pInterface Pointer to this interface.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVideoAccelFlush,(PPDMIVMMDEVCONNECTOR pInterface));
+
+ /**
+ * Return whether the given video mode is supported/wanted by the host.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to this interface.
+ * @param display The guest monitor, 0 for primary.
+ * @param cy Video mode horizontal resolution in pixels.
+ * @param cx Video mode vertical resolution in pixels.
+ * @param cBits Video mode bits per pixel.
+ * @param pfSupported Where to put the indicator for whether this mode is supported. (output)
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVideoModeSupported,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t display, uint32_t cx, uint32_t cy, uint32_t cBits, bool *pfSupported));
+
+ /**
+ * Queries by how many pixels the height should be reduced when calculating video modes
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to this interface.
+ * @param pcyReduction Pointer to the result value.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetHeightReduction,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcyReduction));
+
+ /**
+ * Informs about a credentials judgement result from the guest.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to this interface.
+ * @param fFlags Judgement result flags.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetCredentialsJudgementResult,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t fFlags));
+
+ /**
+ * Set the visible region of the display
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param cRect Number of rectangles in pRect
+ * @param pRect Rectangle array
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetVisibleRegion,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t cRect, PRTRECT pRect));
+
+ /**
+ * Query the visible region of the display
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pcRect Number of rectangles in pRect
+ * @param pRect Rectangle array (set to NULL to query the number of rectangles)
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryVisibleRegion,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcRect, PRTRECT pRect));
+
+ /**
+ * Request the statistics interval
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pulInterval Pointer to interval in seconds
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryStatisticsInterval,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pulInterval));
+
+ /**
+ * Report new guest statistics
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pGuestStats Guest statistics
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReportStatistics,(PPDMIVMMDEVCONNECTOR pInterface, struct VBoxGuestStatistics *pGuestStats));
+
+ /**
+ * Query the current balloon size
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pcbBalloon Balloon size
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryBalloonSize,(PPDMIVMMDEVCONNECTOR pInterface, uint32_t *pcbBalloon));
+
+ /**
+ * Query the current page fusion setting
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pfPageFusionEnabled Pointer to boolean
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnIsPageFusionEnabled,(PPDMIVMMDEVCONNECTOR pInterface, bool *pfPageFusionEnabled));
+
+} PDMIVMMDEVCONNECTOR;
+/** PDMIVMMDEVCONNECTOR interface ID. */
+#define PDMIVMMDEVCONNECTOR_IID "aff90240-a443-434e-9132-80c186ab97d4"
+
+
+/** Pointer to a network connector interface */
+typedef struct PDMIAUDIOCONNECTOR *PPDMIAUDIOCONNECTOR;
+/**
+ * Audio connector interface (up).
+ * No interface pair yet.
+ */
+typedef struct PDMIAUDIOCONNECTOR
+{
+ DECLR3CALLBACKMEMBER(void, pfnRun,(PPDMIAUDIOCONNECTOR pInterface));
+
+/* DECLR3CALLBACKMEMBER(int, pfnSetRecordSource,(PPDMIAUDIOINCONNECTOR pInterface, AUDIORECSOURCE)); */
+
+} PDMIAUDIOCONNECTOR;
+/** PDMIAUDIOCONNECTOR interface ID. */
+#define PDMIAUDIOCONNECTOR_IID "85d52af5-b3aa-4b3e-b176-4b5ebfc52f47"
+
+
+/** @todo r=bird: the two following interfaces are hacks to work around the missing audio driver
+ * interface. This should be addressed rather than making more temporary hacks. */
+
+/** Pointer to a Audio Sniffer Device port interface. */
+typedef struct PDMIAUDIOSNIFFERPORT *PPDMIAUDIOSNIFFERPORT;
+/**
+ * Audio Sniffer port interface (down).
+ * Pair with PDMIAUDIOSNIFFERCONNECTOR.
+ */
+typedef struct PDMIAUDIOSNIFFERPORT
+{
+ /**
+ * Enables or disables sniffing.
+ *
+ * If sniffing is being enabled also sets a flag whether the audio must be also
+ * left on the host.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to this interface.
+ * @param fEnable 'true' for enable sniffing, 'false' to disable.
+ * @param fKeepHostAudio Indicates whether host audio should also present
+ * 'true' means that sound should not be played
+ * by the audio device.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetup,(PPDMIAUDIOSNIFFERPORT pInterface, bool fEnable, bool fKeepHostAudio));
+
+ /**
+ * Enables or disables audio input.
+ *
+ * @returns VBox status code
+ * @param pInterface Pointer to this interface.
+ * @param fIntercept 'true' for interception of audio input,
+ * 'false' to let the host audio backend do audio input.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAudioInputIntercept,(PPDMIAUDIOSNIFFERPORT pInterface, bool fIntercept));
+
+ /**
+ * Audio input is about to start.
+ *
+ * @returns VBox status code.
+ * @param pvContext The callback context, supplied in the
+ * PDMIAUDIOSNIFFERCONNECTOR::pfnAudioInputBegin as pvContext.
+ * @param iSampleHz The sample frequency in Hz.
+ * @param cChannels Number of channels. 1 for mono, 2 for stereo.
+ * @param cBits How many bits a sample for a single channel has. Normally 8 or 16.
+ * @param fUnsigned Whether samples are unsigned values.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAudioInputEventBegin,(PPDMIAUDIOSNIFFERPORT pInterface,
+ void *pvContext,
+ int iSampleHz,
+ int cChannels,
+ int cBits,
+ bool fUnsigned));
+
+ /**
+ * Callback which delivers audio data to the audio device.
+ *
+ * @returns VBox status code.
+ * @param pvContext The callback context, supplied in the
+ * PDMIAUDIOSNIFFERCONNECTOR::pfnAudioInputBegin as pvContext.
+ * @param pvData Event specific data.
+ * @param cbData Size of the buffer pointed by pvData.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAudioInputEventData,(PPDMIAUDIOSNIFFERPORT pInterface,
+ void *pvContext,
+ const void *pvData,
+ uint32_t cbData));
+
+ /**
+ * Audio input ends.
+ *
+ * @param pvContext The callback context, supplied in the
+ * PDMIAUDIOSNIFFERCONNECTOR::pfnAudioInputBegin as pvContext.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnAudioInputEventEnd,(PPDMIAUDIOSNIFFERPORT pInterface,
+ void *pvContext));
+} PDMIAUDIOSNIFFERPORT;
+/** PDMIAUDIOSNIFFERPORT interface ID. */
+#define PDMIAUDIOSNIFFERPORT_IID "8ad25d78-46e9-479b-a363-bb0bc0fe022f"
+
+
+/** Pointer to a Audio Sniffer connector interface. */
+typedef struct PDMIAUDIOSNIFFERCONNECTOR *PPDMIAUDIOSNIFFERCONNECTOR;
+
+/**
+ * Audio Sniffer connector interface (up).
+ * Pair with PDMIAUDIOSNIFFERPORT.
+ */
+typedef struct PDMIAUDIOSNIFFERCONNECTOR
+{
+ /**
+ * AudioSniffer device calls this method when audio samples
+ * are about to be played and sniffing is enabled.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pvSamples Audio samples buffer.
+ * @param cSamples How many complete samples are in the buffer.
+ * @param iSampleHz The sample frequency in Hz.
+ * @param cChannels Number of channels. 1 for mono, 2 for stereo.
+ * @param cBits How many bits a sample for a single channel has. Normally 8 or 16.
+ * @param fUnsigned Whether samples are unsigned values.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnAudioSamplesOut,(PPDMIAUDIOSNIFFERCONNECTOR pInterface, void *pvSamples, uint32_t cSamples,
+ int iSampleHz, int cChannels, int cBits, bool fUnsigned));
+
+ /**
+ * AudioSniffer device calls this method when output volume is changed.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param u16LeftVolume 0..0xFFFF volume level for left channel.
+ * @param u16RightVolume 0..0xFFFF volume level for right channel.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnAudioVolumeOut,(PPDMIAUDIOSNIFFERCONNECTOR pInterface, uint16_t u16LeftVolume, uint16_t u16RightVolume));
+
+ /**
+ * Audio input has been requested by the virtual audio device.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param ppvUserCtx The interface context for this audio input stream,
+ * it will be used in the pfnAudioInputEnd call.
+ * @param pvContext The context pointer to be used in PDMIAUDIOSNIFFERPORT::pfnAudioInputEvent.
+ * @param cSamples How many samples in a block is preferred in
+ * PDMIAUDIOSNIFFERPORT::pfnAudioInputEvent.
+ * @param iSampleHz The sample frequency in Hz.
+ * @param cChannels Number of channels. 1 for mono, 2 for stereo.
+ * @param cBits How many bits a sample for a single channel has. Normally 8 or 16.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAudioInputBegin,(PPDMIAUDIOSNIFFERCONNECTOR pInterface,
+ void **ppvUserCtx,
+ void *pvContext,
+ uint32_t cSamples,
+ uint32_t iSampleHz,
+ uint32_t cChannels,
+ uint32_t cBits));
+
+ /**
+ * Audio input has been requested by the virtual audio device.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pvUserCtx The interface context for this audio input stream,
+ * which was returned by pfnAudioInputBegin call.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnAudioInputEnd,(PPDMIAUDIOSNIFFERCONNECTOR pInterface,
+ void *pvUserCtx));
+} PDMIAUDIOSNIFFERCONNECTOR;
+/** PDMIAUDIOSNIFFERCONNECTOR - The Audio Sniffer Driver connector interface. */
+#define PDMIAUDIOSNIFFERCONNECTOR_IID "9d37f543-27af-45f8-8002-8ef7abac71e4"
+
+
+/**
+ * Generic status LED core.
+ * Note that a unit doesn't have to support all the indicators.
+ */
+typedef union PDMLEDCORE
+{
+ /** 32-bit view. */
+ uint32_t volatile u32;
+ /** Bit view. */
+ struct
+ {
+ /** Reading/Receiving indicator. */
+ uint32_t fReading : 1;
+ /** Writing/Sending indicator. */
+ uint32_t fWriting : 1;
+ /** Busy indicator. */
+ uint32_t fBusy : 1;
+ /** Error indicator. */
+ uint32_t fError : 1;
+ } s;
+} PDMLEDCORE;
+
+/** LED bit masks for the u32 view.
+ * @{ */
+/** Reading/Receiving indicator. */
+#define PDMLED_READING RT_BIT(0)
+/** Writing/Sending indicator. */
+#define PDMLED_WRITING RT_BIT(1)
+/** Busy indicator. */
+#define PDMLED_BUSY RT_BIT(2)
+/** Error indicator. */
+#define PDMLED_ERROR RT_BIT(3)
+/** @} */
+
+
+/**
+ * Generic status LED.
+ * Note that a unit doesn't have to support all the indicators.
+ */
+typedef struct PDMLED
+{
+ /** Just a magic for sanity checking. */
+ uint32_t u32Magic;
+ uint32_t u32Alignment; /**< structure size alignment. */
+ /** The actual LED status.
+ * Only the device is allowed to change this. */
+ PDMLEDCORE Actual;
+ /** The asserted LED status which is cleared by the reader.
+ * The device will assert the bits but never clear them.
+ * The driver clears them as it sees fit. */
+ PDMLEDCORE Asserted;
+} PDMLED;
+
+/** Pointer to an LED. */
+typedef PDMLED *PPDMLED;
+/** Pointer to a const LED. */
+typedef const PDMLED *PCPDMLED;
+
+/** Magic value for PDMLED::u32Magic. */
+#define PDMLED_MAGIC UINT32_C(0x11335577)
+
+/** Pointer to an LED ports interface. */
+typedef struct PDMILEDPORTS *PPDMILEDPORTS;
+/**
+ * Interface for exporting LEDs (down).
+ * Pair with PDMILEDCONNECTORS.
+ */
+typedef struct PDMILEDPORTS
+{
+ /**
+ * Gets the pointer to the status LED of a unit.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param iLUN The unit which status LED we desire.
+ * @param ppLed Where to store the LED pointer.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryStatusLed,(PPDMILEDPORTS pInterface, unsigned iLUN, PPDMLED *ppLed));
+
+} PDMILEDPORTS;
+/** PDMILEDPORTS interface ID. */
+#define PDMILEDPORTS_IID "435e0cec-8549-4ca0-8c0d-98e52f1dc038"
+
+
+/** Pointer to an LED connectors interface. */
+typedef struct PDMILEDCONNECTORS *PPDMILEDCONNECTORS;
+/**
+ * Interface for reading LEDs (up).
+ * Pair with PDMILEDPORTS.
+ */
+typedef struct PDMILEDCONNECTORS
+{
+ /**
+ * Notification about a unit which have been changed.
+ *
+ * The driver must discard any pointers to data owned by
+ * the unit and requery it.
+ *
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param iLUN The unit number.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnUnitChanged,(PPDMILEDCONNECTORS pInterface, unsigned iLUN));
+} PDMILEDCONNECTORS;
+/** PDMILEDCONNECTORS interface ID. */
+#define PDMILEDCONNECTORS_IID "8ed63568-82a7-4193-b57b-db8085ac4495"
+
+
+/** Pointer to a Media Notification interface. */
+typedef struct PDMIMEDIANOTIFY *PPDMIMEDIANOTIFY;
+/**
+ * Interface for exporting Medium eject information (up). No interface pair.
+ */
+typedef struct PDMIMEDIANOTIFY
+{
+ /**
+ * Signals that the medium was ejected.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param iLUN The unit which had the medium ejected.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnEjected,(PPDMIMEDIANOTIFY pInterface, unsigned iLUN));
+
+} PDMIMEDIANOTIFY;
+/** PDMIMEDIANOTIFY interface ID. */
+#define PDMIMEDIANOTIFY_IID "fc22d53e-feb1-4a9c-b9fb-0a990a6ab288"
+
+
+/** The special status unit number */
+#define PDM_STATUS_LUN 999
+
+
+#ifdef VBOX_WITH_HGCM
+
+/** Abstract HGCM command structure. Used only to define a typed pointer. */
+struct VBOXHGCMCMD;
+
+/** Pointer to HGCM command structure. This pointer is unique and identifies
+ * the command being processed. The pointer is passed to HGCM connector methods,
+ * and must be passed back to HGCM port when command is completed.
+ */
+typedef struct VBOXHGCMCMD *PVBOXHGCMCMD;
+
+/** Pointer to a HGCM port interface. */
+typedef struct PDMIHGCMPORT *PPDMIHGCMPORT;
+/**
+ * Host-Guest communication manager port interface (down). Normally implemented
+ * by VMMDev.
+ * Pair with PDMIHGCMCONNECTOR.
+ */
+typedef struct PDMIHGCMPORT
+{
+ /**
+ * Notify the guest on a command completion.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param rc The return code (VBox error code).
+ * @param pCmd A pointer that identifies the completed command.
+ *
+ * @returns VBox status code
+ */
+ DECLR3CALLBACKMEMBER(void, pfnCompleted,(PPDMIHGCMPORT pInterface, int32_t rc, PVBOXHGCMCMD pCmd));
+
+} PDMIHGCMPORT;
+/** PDMIHGCMPORT interface ID. */
+# define PDMIHGCMPORT_IID "e00a0cbf-b75a-45c3-87f4-41cddbc5ae0b"
+
+
+/** Pointer to a HGCM service location structure. */
+typedef struct HGCMSERVICELOCATION *PHGCMSERVICELOCATION;
+
+/** Pointer to a HGCM connector interface. */
+typedef struct PDMIHGCMCONNECTOR *PPDMIHGCMCONNECTOR;
+/**
+ * The Host-Guest communication manager connector interface (up). Normally
+ * implemented by Main::VMMDevInterface.
+ * Pair with PDMIHGCMPORT.
+ */
+typedef struct PDMIHGCMCONNECTOR
+{
+ /**
+ * Locate a service and inform it about a client connection.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pCmd A pointer that identifies the command.
+ * @param pServiceLocation Pointer to the service location structure.
+ * @param pu32ClientID Where to store the client id for the connection.
+ * @return VBox status code.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnConnect,(PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, PHGCMSERVICELOCATION pServiceLocation, uint32_t *pu32ClientID));
+
+ /**
+ * Disconnect from service.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pCmd A pointer that identifies the command.
+ * @param u32ClientID The client id returned by the pfnConnect call.
+ * @return VBox status code.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDisconnect,(PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID));
+
+ /**
+ * Process a guest issued command.
+ *
+ * @param pInterface Pointer to this interface.
+ * @param pCmd A pointer that identifies the command.
+ * @param u32ClientID The client id returned by the pfnConnect call.
+ * @param u32Function Function to be performed by the service.
+ * @param cParms Number of parameters in the array pointed to by paParams.
+ * @param paParms Pointer to an array of parameters.
+ * @return VBox status code.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnCall,(PPDMIHGCMCONNECTOR pInterface, PVBOXHGCMCMD pCmd, uint32_t u32ClientID, uint32_t u32Function,
+ uint32_t cParms, PVBOXHGCMSVCPARM paParms));
+
+} PDMIHGCMCONNECTOR;
+/** PDMIHGCMCONNECTOR interface ID. */
+# define PDMIHGCMCONNECTOR_IID "a1104758-c888-4437-8f2a-7bac17865b5c"
+
+#endif /* VBOX_WITH_HGCM */
+
+/**
+ * Data direction.
+ */
+typedef enum PDMSCSIREQUESTTXDIR
+{
+ PDMSCSIREQUESTTXDIR_UNKNOWN = 0x00,
+ PDMSCSIREQUESTTXDIR_FROM_DEVICE = 0x01,
+ PDMSCSIREQUESTTXDIR_TO_DEVICE = 0x02,
+ PDMSCSIREQUESTTXDIR_NONE = 0x03,
+ PDMSCSIREQUESTTXDIR_32BIT_HACK = 0x7fffffff
+} PDMSCSIREQUESTTXDIR;
+
+/**
+ * SCSI request structure.
+ */
+typedef struct PDMSCSIREQUEST
+{
+ /** The logical unit. */
+ uint32_t uLogicalUnit;
+ /** Direction of the data flow. */
+ PDMSCSIREQUESTTXDIR uDataDirection;
+ /** Size of the SCSI CDB. */
+ uint32_t cbCDB;
+ /** Pointer to the SCSI CDB. */
+ uint8_t *pbCDB;
+ /** Overall size of all scatter gather list elements
+ * for data transfer if any. */
+ uint32_t cbScatterGather;
+ /** Number of elements in the scatter gather list. */
+ uint32_t cScatterGatherEntries;
+ /** Pointer to the head of the scatter gather list. */
+ PRTSGSEG paScatterGatherHead;
+ /** Size of the sense buffer. */
+ uint32_t cbSenseBuffer;
+ /** Pointer to the sense buffer. *
+ * Current assumption that the sense buffer is not scattered. */
+ uint8_t *pbSenseBuffer;
+ /** Opaque user data for use by the device. Left untouched by everything else! */
+ void *pvUser;
+} PDMSCSIREQUEST, *PPDMSCSIREQUEST;
+/** Pointer to a const SCSI request structure. */
+typedef const PDMSCSIREQUEST *PCSCSIREQUEST;
+
+/** Pointer to a SCSI port interface. */
+typedef struct PDMISCSIPORT *PPDMISCSIPORT;
+/**
+ * SCSI command execution port interface (down).
+ * Pair with PDMISCSICONNECTOR.
+ */
+typedef struct PDMISCSIPORT
+{
+
+ /**
+ * Notify the device on request completion.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pSCSIRequest Pointer to the finished SCSI request.
+ * @param rcCompletion SCSI_STATUS_* code for the completed request.
+ * @param fRedo Flag whether the request can to be redone
+ * when it failed.
+ * @param rcReq The status code the request completed with (VERR_*)
+ * Should be only used to choose the correct error message
+ * displayed to the user if the error can be fixed by him
+ * (fRedo is true).
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSCSIRequestCompleted, (PPDMISCSIPORT pInterface, PPDMSCSIREQUEST pSCSIRequest,
+ int rcCompletion, bool fRedo, int rcReq));
+
+ /**
+ * Returns the storage controller name, instance and LUN of the attached medium.
+ *
+ * @returns VBox status.
+ * @param pInterface Pointer to this interface.
+ * @param ppcszController Where to store the name of the storage controller.
+ * @param piInstance Where to store the instance number of the controller.
+ * @param piLUN Where to store the LUN of the attached device.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryDeviceLocation, (PPDMISCSIPORT pInterface, const char **ppcszController,
+ uint32_t *piInstance, uint32_t *piLUN));
+
+} PDMISCSIPORT;
+/** PDMISCSIPORT interface ID. */
+#define PDMISCSIPORT_IID "05d9fc3b-e38c-4b30-8344-a323feebcfe5"
+
+
+/** Pointer to a SCSI connector interface. */
+typedef struct PDMISCSICONNECTOR *PPDMISCSICONNECTOR;
+/**
+ * SCSI command execution connector interface (up).
+ * Pair with PDMISCSIPORT.
+ */
+typedef struct PDMISCSICONNECTOR
+{
+
+ /**
+ * Submits a SCSI request for execution.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to this interface.
+ * @param pSCSIRequest Pointer to the SCSI request to execute.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSCSIRequestSend, (PPDMISCSICONNECTOR pInterface, PPDMSCSIREQUEST pSCSIRequest));
+
+} PDMISCSICONNECTOR;
+/** PDMISCSICONNECTOR interface ID. */
+#define PDMISCSICONNECTOR_IID "94465fbd-a2f2-447e-88c9-7366421bfbfe"
+
+
+/** Pointer to a display VBVA callbacks interface. */
+typedef struct PDMIDISPLAYVBVACALLBACKS *PPDMIDISPLAYVBVACALLBACKS;
+/**
+ * Display VBVA callbacks interface (up).
+ */
+typedef struct PDMIDISPLAYVBVACALLBACKS
+{
+
+ /**
+ * Informs guest about completion of processing the given Video HW Acceleration
+ * command, does not wait for the guest to process the command.
+ *
+ * @returns ???
+ * @param pInterface Pointer to this interface.
+ * @param pCmd The Video HW Acceleration Command that was
+ * completed.
+ * @todo r=bird: if async means asynchronous; then
+ * s/pfnVHWACommandCompleteAsynch/pfnVHWACommandCompleteAsync/;
+ * fi
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVHWACommandCompleteAsynch, (PPDMIDISPLAYVBVACALLBACKS pInterface,
+ PVBOXVHWACMD pCmd));
+
+ DECLR3CALLBACKMEMBER(int, pfnCrHgsmiCommandCompleteAsync, (PPDMIDISPLAYVBVACALLBACKS pInterface,
+ PVBOXVDMACMD_CHROMIUM_CMD pCmd, int rc));
+
+ DECLR3CALLBACKMEMBER(int, pfnCrHgsmiControlCompleteAsync, (PPDMIDISPLAYVBVACALLBACKS pInterface,
+ PVBOXVDMACMD_CHROMIUM_CTL pCmd, int rc));
+} PDMIDISPLAYVBVACALLBACKS;
+/** PDMIDISPLAYVBVACALLBACKS */
+#define PDMIDISPLAYVBVACALLBACKS_IID "b78b81d2-c821-4e66-96ff-dbafa76343a5"
+
+/** Pointer to a PCI raw connector interface. */
+typedef struct PDMIPCIRAWCONNECTOR *PPDMIPCIRAWCONNECTOR;
+/**
+ * PCI raw connector interface (up).
+ */
+typedef struct PDMIPCIRAWCONNECTOR
+{
+
+ /**
+ *
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDeviceConstructComplete, (PPDMIPCIRAWCONNECTOR pInterface, const char *pcszName,
+ uint32_t uHostPciAddress, uint32_t uGuestPciAddress,
+ int rc));
+
+} PDMIPCIRAWCONNECTOR;
+/** PDMIPCIRAWCONNECTOR interface ID. */
+#define PDMIPCIRAWCONNECTOR_IID "14aa9c6c-8869-4782-9dfc-910071a6aebf"
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
diff --git a/include/VBox/vmm/pdmins.h b/include/VBox/vmm/pdmins.h
new file mode 100644
index 00000000..2375f3c4
--- /dev/null
+++ b/include/VBox/vmm/pdmins.h
@@ -0,0 +1,70 @@
+/** @file
+ * PDM - Pluggable Device Manager, Common Instance Macros.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmins_h
+#define ___VBox_vmm_pdmins_h
+
+
+/** @defgroup grp_pdm_ins Common PDM Instance Macros
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/** @def PDMBOTHCBDECL
+ * Macro for declaring a callback which is static in HC and exported in GC.
+ */
+#if defined(IN_RC) || defined(IN_RING0)
+# ifdef __cplusplus
+# define PDMBOTHCBDECL(type) extern "C" DECLEXPORT(type)
+# else
+# define PDMBOTHCBDECL(type) DECLEXPORT(type)
+# endif
+#else
+# define PDMBOTHCBDECL(type) static type
+#endif
+
+/** @def PDMINS_2_DATA
+ * Converts a PDM Device, USB Device, or Driver instance pointer to a pointer to the instance data.
+ */
+#define PDMINS_2_DATA(pIns, type) ( (type)(void *)&(pIns)->achInstanceData[0] )
+
+/** @def PDMINS_2_DATA_RCPTR
+ * Converts a PDM Device, USB Device, or Driver instance pointer to a RC pointer to the instance data.
+ */
+#define PDMINS_2_DATA_RCPTR(pIns) ( (pIns)->pvInstanceDataRC )
+
+/** @def PDMINS_2_DATA_R3PTR
+ * Converts a PDM Device, USB Device, or Driver instance pointer to a HC pointer to the instance data.
+ */
+#define PDMINS_2_DATA_R3PTR(pIns) ( (pIns)->pvInstanceDataR3 )
+
+/** @def PDMINS_2_DATA_R0PTR
+ * Converts a PDM Device, USB Device, or Driver instance pointer to a R0 pointer to the instance data.
+ */
+#define PDMINS_2_DATA_R0PTR(pIns) ( (pIns)->pvInstanceDataR0 )
+
+/** @} */
+
+#endif
diff --git a/include/VBox/vmm/pdmnetifs.h b/include/VBox/vmm/pdmnetifs.h
new file mode 100644
index 00000000..e9280440
--- /dev/null
+++ b/include/VBox/vmm/pdmnetifs.h
@@ -0,0 +1,437 @@
+/** @file
+ * PDM - Pluggable Device Manager, Network Interfaces.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmnetifs_h
+#define ___VBox_vmm_pdmnetifs_h
+
+#include <VBox/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_ifs_net PDM Network Interfaces
+ * @ingroup grp_pdm_interfaces
+ * @{
+ */
+
+
+/**
+ * PDM scatter/gather buffer.
+ *
+ * @todo Promote this to VBox/types.h, VBox/vmm/pdmcommon.h or some such place.
+ */
+typedef struct PDMSCATTERGATHER
+{
+ /** Flags. */
+ size_t fFlags;
+ /** The number of bytes used.
+ * This is cleared on alloc and set by the user. */
+ size_t cbUsed;
+ /** The number of bytes available.
+ * This is set on alloc and not changed by the user. */
+ size_t cbAvailable;
+ /** Private data member for the allocator side. */
+ void *pvAllocator;
+ /** Private data member for the user side. */
+ void *pvUser;
+ /** The number of segments
+ * This is set on alloc and not changed by the user. */
+ size_t cSegs;
+ /** Variable sized array of segments. */
+ PDMDATASEG aSegs[1];
+} PDMSCATTERGATHER;
+/** Pointer to a PDM scatter/gather buffer. */
+typedef PDMSCATTERGATHER *PPDMSCATTERGATHER;
+/** Pointer to a PDM scatter/gather buffer pointer. */
+typedef PPDMSCATTERGATHER *PPPDMSCATTERGATHER;
+
+
+/** @name PDMSCATTERGATHER::fFlags
+ * @{ */
+/** Magic value. */
+#define PDMSCATTERGATHER_FLAGS_MAGIC UINT32_C(0xb1b10000)
+/** Magic mask. */
+#define PDMSCATTERGATHER_FLAGS_MAGIC_MASK UINT32_C(0xffff0000)
+/** Owned by owner number 1. */
+#define PDMSCATTERGATHER_FLAGS_OWNER_1 UINT32_C(0x00000001)
+/** Owned by owner number 2. */
+#define PDMSCATTERGATHER_FLAGS_OWNER_2 UINT32_C(0x00000002)
+/** Owned by owner number 3. */
+#define PDMSCATTERGATHER_FLAGS_OWNER_3 UINT32_C(0x00000002)
+/** Owner mask. */
+#define PDMSCATTERGATHER_FLAGS_OWNER_MASK UINT32_C(0x00000003)
+/** Mask of flags available to general use.
+ * The parties using the SG must all agree upon how to use these of course. */
+#define PDMSCATTERGATHER_FLAGS_AVL_MASK UINT32_C(0x0000f000)
+/** Flags reserved for future use, MBZ. */
+#define PDMSCATTERGATHER_FLAGS_RVD_MASK UINT32_C(0x00000ff8)
+/** @} */
+
+
+/**
+ * Sets the owner of a scatter/gather buffer.
+ *
+ * @param pSgBuf .
+ * @param uNewOwner The new owner.
+ */
+DECLINLINE(void) PDMScatterGatherSetOwner(PPDMSCATTERGATHER pSgBuf, uint32_t uNewOwner)
+{
+ pSgBuf->fFlags = (pSgBuf->fFlags & ~PDMSCATTERGATHER_FLAGS_OWNER_MASK) | uNewOwner;
+}
+
+
+
+/** Pointer to a network port interface */
+typedef struct PDMINETWORKDOWN *PPDMINETWORKDOWN;
+/**
+ * Network port interface (down).
+ * Pair with PDMINETWORKUP.
+ */
+typedef struct PDMINETWORKDOWN
+{
+ /**
+ * Wait until there is space for receiving data. We do not care how much space is available
+ * because pfnReceive() will re-check and notify the guest if necessary.
+ *
+ * This function must be called before the pfnRecieve() method is called.
+ *
+ * @returns VBox status code. VINF_SUCCESS means there is at least one receive descriptor available.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param cMillies Number of milliseconds to wait. 0 means return immediately.
+ *
+ * @thread Non-EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnWaitReceiveAvail,(PPDMINETWORKDOWN pInterface, RTMSINTERVAL cMillies));
+
+ /**
+ * Receive data from the network.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf The available data.
+ * @param cb Number of bytes available in the buffer.
+ *
+ * @thread Non-EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReceive,(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb));
+
+ /**
+ * Receive data with segmentation context from the network.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pvBuf The available data.
+ * @param cb Number of bytes available in the buffer.
+ * @param pGso Segmentation context.
+ *
+ * @thread Non-EMT.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReceiveGso,(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb, PCPDMNETWORKGSO pGso));
+
+ /**
+ * Do pending transmit work on the leaf driver's XMIT thread.
+ *
+ * When a PDMINETWORKUP::pfnBeginTransmit or PDMINETWORKUP::pfnAllocBuf call
+ * fails with VERR_TRY_AGAIN, the leaf drivers XMIT thread will offer to process
+ * the upstream device/driver when the the VERR_TRY_AGAIN condition has been
+ * removed. In some cases the VERR_TRY_AGAIN condition is simply being in an
+ * inconvenient context and the XMIT thread will start working ASAP.
+ *
+ * @param pInterface Pointer to this interface.
+ * @thread Non-EMT.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnXmitPending,(PPDMINETWORKDOWN pInterface));
+
+} PDMINETWORKDOWN;
+/** PDMINETWORKDOWN interface ID. */
+#define PDMINETWORKDOWN_IID "52b8cdbb-a087-493b-baa7-81ec3b803e06"
+
+
+/**
+ * Network link state.
+ */
+typedef enum PDMNETWORKLINKSTATE
+{
+ /** Invalid state. */
+ PDMNETWORKLINKSTATE_INVALID = 0,
+ /** The link is up. */
+ PDMNETWORKLINKSTATE_UP,
+ /** The link is down. */
+ PDMNETWORKLINKSTATE_DOWN,
+ /** The link is temporarily down while resuming. */
+ PDMNETWORKLINKSTATE_DOWN_RESUME
+} PDMNETWORKLINKSTATE;
+
+
+/** Pointer to a network connector interface */
+typedef R3PTRTYPE(struct PDMINETWORKUP *) PPDMINETWORKUPR3;
+/** Pointer to a network connector interface, ring-0 context. */
+typedef R0PTRTYPE(struct PDMINETWORKUPR0 *) PPDMINETWORKUPR0;
+/** Pointer to a network connector interface, raw-mode context. */
+typedef RCPTRTYPE(struct PDMINETWORKUPRC *) PPDMINETWORKUPRC;
+/** Pointer to a current context network connector interface. */
+typedef CTX_SUFF(PPDMINETWORKUP) PPDMINETWORKUP;
+
+/**
+ * Network connector interface (up).
+ * Pair with PDMINETWORKDOWN.
+ */
+typedef struct PDMINETWORKUP
+{
+ /**
+ * Begins a transmit session.
+ *
+ * The leaf driver guarantees that there are no concurrent sessions.
+ *
+ * @retval VINF_SUCCESS on success. Must always call
+ * PDMINETWORKUP::pfnEndXmit.
+ * @retval VERR_TRY_AGAIN if there is already an open transmit session or some
+ * important resource was unavailable (like buffer space). If it's a
+ * resources issue, the driver will signal its XMIT thread and have it
+ * work the device thru the PDMINETWORKDOWN::pfnNotifyBufAvailable
+ * callback method.
+ *
+ * @param pInterface Pointer to the interface structure containing the
+ * called function pointer.
+ * @param fOnWorkerThread Set if we're being called on a work thread. Clear
+ * if an EMT.
+ *
+ * @thread Any, but normally EMT or the XMIT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnBeginXmit,(PPDMINETWORKUP pInterface, bool fOnWorkerThread));
+
+ /**
+ * Get a send buffer for passing to pfnSendBuf.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_TRY_AGAIN if temporarily out of buffer space. After this
+ * happens, the driver will call PDMINETWORKDOWN::pfnNotifyBufAvailable
+ * when this is a buffer of the required size available.
+ * @retval VERR_NO_MEMORY if really out of buffer space.
+ * @retval VERR_NET_DOWN if we cannot send anything to the network at this
+ * point in time. Drop the frame with a xmit error. This is typically
+ * only seen when pausing the VM since the device keeps the link state,
+ * but there could of course be races.
+ *
+ * @param pInterface Pointer to the interface structure containing the
+ * called function pointer.
+ * @param cbMin The minimum buffer size.
+ * @param pGso Pointer to a GSO context (only reference while in
+ * this call). NULL indicates no segmentation
+ * offloading. PDMSCATTERGATHER::pvUser is used to
+ * indicate that a network SG uses GSO, usually by
+ * pointing to a copy of @a pGso.
+ * @param ppSgBuf Where to return the buffer. The buffer will be
+ * owned by the caller, designation owner number 1.
+ *
+ * @thread Any, but normally EMT or the XMIT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnAllocBuf,(PPDMINETWORKUP pInterface, size_t cbMin, PCPDMNETWORKGSO pGso,
+ PPPDMSCATTERGATHER ppSgBuf));
+
+ /**
+ * Frees an unused buffer.
+ *
+ * @retval VINF_SUCCESS on success.
+ *
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pSgBuf A buffer from PDMINETWORKUP::pfnAllocBuf or
+ * PDMINETWORKDOWN::pfnNotifyBufAvailable. The buffer
+ * ownership shall be 1.
+ *
+ * @thread Any, but normally EMT or the XMIT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFreeBuf,(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf));
+
+ /**
+ * Send data to the network.
+ *
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_NET_DOWN if the NIC is not connected to a network. pSgBuf will
+ * be freed.
+ * @retval VERR_NET_NO_BUFFER_SPACE if we're out of resources. pSgBuf will be
+ * freed.
+ *
+ * @param pInterface Pointer to the interface structure containing the
+ * called function pointer.
+ * @param pSgBuf The buffer containing the data to send. The buffer
+ * ownership shall be 1. The buffer will always be
+ * consumed, regardless of the status code.
+ *
+ * @param fOnWorkerThread Set if we're being called on a work thread. Clear
+ * if an EMT.
+ *
+ * @thread Any, but normally EMT or the XMIT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSendBuf,(PPDMINETWORKUP pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread));
+
+ /**
+ * Ends a transmit session.
+ *
+ * Pairs with successful PDMINETWORKUP::pfnBeginXmit calls.
+ *
+ * @param pInterface Pointer to the interface structure containing the
+ * called function pointer.
+ *
+ * @thread Any, but normally EMT or the XMIT thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnEndXmit,(PPDMINETWORKUP pInterface));
+
+ /**
+ * Set promiscuous mode.
+ *
+ * This is called when the promiscuous mode is set. This means that there doesn't have
+ * to be a mode change when it's called.
+ *
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param fPromiscuous Set if the adaptor is now in promiscuous mode. Clear if it is not.
+ * @thread EMT ??
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSetPromiscuousMode,(PPDMINETWORKUP pInterface, bool fPromiscuous));
+
+ /**
+ * Notification on link status changes.
+ *
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param enmLinkState The new link state.
+ * @thread EMT ??
+ */
+ DECLR3CALLBACKMEMBER(void, pfnNotifyLinkChanged,(PPDMINETWORKUP pInterface, PDMNETWORKLINKSTATE enmLinkState));
+
+ /** @todo Add a callback that informs the driver chain about MAC address changes if we ever implement that. */
+
+} PDMINETWORKUP;
+
+/** Ring-0 edition of PDMINETWORKUP. */
+typedef struct PDMINETWORKUPR0
+{
+ /** @copydoc PDMINETWORKUP::pfnBeginXmit */
+ DECLR0CALLBACKMEMBER(int, pfnBeginXmit,(PPDMINETWORKUPR0 pInterface, bool fOnWorkerThread));
+ /** @copydoc PDMINETWORKUP::pfnAllocBuf */
+ DECLR0CALLBACKMEMBER(int, pfnAllocBuf,(PPDMINETWORKUPR0 pInterface, size_t cbMin, PCPDMNETWORKGSO pGso,
+ PPPDMSCATTERGATHER ppSgBuf));
+ /** @copydoc PDMINETWORKUP::pfnFreeBuf */
+ DECLR0CALLBACKMEMBER(int, pfnFreeBuf,(PPDMINETWORKUPR0 pInterface, PPDMSCATTERGATHER pSgBuf));
+ /** @copydoc PDMINETWORKUP::pfnSendBuf */
+ DECLR0CALLBACKMEMBER(int, pfnSendBuf,(PPDMINETWORKUPR0 pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread));
+ /** @copydoc PDMINETWORKUP::pfnEndBuf */
+ DECLR0CALLBACKMEMBER(void, pfnEndXmit,(PPDMINETWORKUPR0 pInterface));
+ /** @copydoc PDMINETWORKUP::pfnSetPromiscuousMode */
+ DECLR0CALLBACKMEMBER(void, pfnSetPromiscuousMode,(PPDMINETWORKUPR0 pInterface, bool fPromiscuous));
+} PDMINETWORKUPR0;
+
+/** Raw-mode context edition of PDMINETWORKUP. */
+typedef struct PDMINETWORKUPRC
+{
+ /** @copydoc PDMINETWORKUP::pfnBeginXmit */
+ DECLRCCALLBACKMEMBER(int, pfnBeginXmit,(PPDMINETWORKUPRC pInterface, bool fOnWorkerThread));
+ /** @copydoc PDMINETWORKUP::pfnAllocBuf */
+ DECLRCCALLBACKMEMBER(int, pfnAllocBuf,(PPDMINETWORKUPRC pInterface, size_t cbMin, PCPDMNETWORKGSO pGso,
+ PPPDMSCATTERGATHER ppSgBuf));
+ /** @copydoc PDMINETWORKUP::pfnFreeBuf */
+ DECLRCCALLBACKMEMBER(int, pfnFreeBuf,(PPDMINETWORKUPRC pInterface, PPDMSCATTERGATHER pSgBuf));
+ /** @copydoc PDMINETWORKUP::pfnSendBuf */
+ DECLRCCALLBACKMEMBER(int, pfnSendBuf,(PPDMINETWORKUPRC pInterface, PPDMSCATTERGATHER pSgBuf, bool fOnWorkerThread));
+ /** @copydoc PDMINETWORKUP::pfnEndBuf */
+ DECLRCCALLBACKMEMBER(void, pfnEndXmit,(PPDMINETWORKUPRC pInterface));
+ /** @copydoc PDMINETWORKUP::pfnSetPromiscuousMode */
+ DECLRCCALLBACKMEMBER(void, pfnSetPromiscuousMode,(PPDMINETWORKUPRC pInterface, bool fPromiscuous));
+} PDMINETWORKUPRC;
+
+/** PDMINETWORKUP interface ID. */
+#define PDMINETWORKUP_IID "67e7e7a8-2594-4649-a1e3-7cee680c6083"
+/** PDMINETWORKUP interface method names. */
+#define PDMINETWORKUP_SYM_LIST "BeginXmit;AllocBuf;FreeBuf;SendBuf;EndXmit;SetPromiscuousMode"
+
+
+/** Pointer to a network config port interface */
+typedef struct PDMINETWORKCONFIG *PPDMINETWORKCONFIG;
+/**
+ * Network config port interface (main).
+ * No interface pair.
+ */
+typedef struct PDMINETWORKCONFIG
+{
+ /**
+ * Gets the current Media Access Control (MAC) address.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param pMac Where to store the MAC address.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnGetMac,(PPDMINETWORKCONFIG pInterface, PRTMAC pMac));
+
+ /**
+ * Gets the new link state.
+ *
+ * @returns The current link state.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(PDMNETWORKLINKSTATE, pfnGetLinkState,(PPDMINETWORKCONFIG pInterface));
+
+ /**
+ * Sets the new link state.
+ *
+ * @returns VBox status code.
+ * @param pInterface Pointer to the interface structure containing the called function pointer.
+ * @param enmState The new link state
+ * @thread EMT
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetLinkState,(PPDMINETWORKCONFIG pInterface, PDMNETWORKLINKSTATE enmState));
+
+} PDMINETWORKCONFIG;
+/** PDMINETWORKCONFIG interface ID. */
+#define PDMINETWORKCONFIG_IID "d6d909e8-716d-415d-b109-534e4478ff4e"
+
+
+/** Pointer to a NAT configuration port. */
+typedef struct PDMINETWORKNATCONFIG *PPDMINETWORKNATCONFIG;
+/**
+ * Network config port interface (main).
+ * No interface pair.
+ */
+typedef struct PDMINETWORKNATCONFIG
+{
+ /**
+ * Inform NAT about the adding/removing redirection rule
+ *
+ * @todo D O C U M E N T M E !
+ * @todo s/u16/u/g
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRedirectRuleCommand ,(PPDMINETWORKNATCONFIG pInterface, bool fRemove,
+ bool fUdp, const char *pHostIp, uint16_t u16HostPort,
+ const char *pGuestIp, uint16_t u16GuestPort));
+
+} PDMINETWORKNATCONFIG;
+/** PDMINETWORKNATCONFIG interface ID. */
+#define PDMINETWORKNATCONFIG_IID "0f001d62-4d2f-11df-93b3-2fd0b3a36a6b"
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/pdmnetinline.h b/include/VBox/vmm/pdmnetinline.h
new file mode 100644
index 00000000..66c3078f
--- /dev/null
+++ b/include/VBox/vmm/pdmnetinline.h
@@ -0,0 +1,664 @@
+/** @file
+ * PDM - Networking Helpers, Inlined Code. (DEV,++)
+ *
+ * This is all inlined because it's too tedious to create 2-3 libraries to
+ * contain it all (same bad excuse as for intnetinline.h).
+ */
+
+/*
+ * Copyright (C) 2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+/*******************************************************************************
+* Header Files *
+*******************************************************************************/
+#include <VBox/log.h>
+#include <VBox/types.h>
+#include <iprt/asm.h>
+#include <iprt/assert.h>
+#include <iprt/net.h>
+#include <iprt/string.h>
+
+
+/**
+ * Checksum type.
+ */
+typedef enum PDMNETCSUMTYPE
+{
+ /** No checksum. */
+ PDMNETCSUMTYPE_NONE = 0,
+ /** Normal TCP checksum. */
+ PDMNETCSUMTYPE_COMPLETE,
+ /** Checksum on pseudo header (used with GSO). */
+ PDMNETCSUMTYPE_PSEUDO,
+ /** The usual 32-bit hack. */
+ PDMNETCSUMTYPE_32_BIT_HACK = 0x7fffffff
+} PDMNETCSUMTYPE;
+
+
+/**
+ * Validates the GSO context.
+ *
+ * @returns true if valid, false if not (not asserted or logged).
+ * @param pGso The GSO context.
+ * @param cbGsoMax The max size of the GSO context.
+ * @param cbFrame The max size of the GSO frame (use to validate
+ * the MSS).
+ */
+DECLINLINE(bool) PDMNetGsoIsValid(PCPDMNETWORKGSO pGso, size_t cbGsoMax, size_t cbFrame)
+{
+ PDMNETWORKGSOTYPE enmType;
+
+ if (RT_UNLIKELY(cbGsoMax < sizeof(*pGso)))
+ return false;
+
+ enmType = (PDMNETWORKGSOTYPE)pGso->u8Type;
+ if (RT_UNLIKELY( enmType <= PDMNETWORKGSOTYPE_INVALID || enmType >= PDMNETWORKGSOTYPE_END ))
+ return false;
+
+ /* all types requires both headers. */
+ if (RT_UNLIKELY( pGso->offHdr1 < sizeof(RTNETETHERHDR) ))
+ return false;
+ if (RT_UNLIKELY( pGso->offHdr2 <= pGso->offHdr1 ))
+ return false;
+ if (RT_UNLIKELY( pGso->cbHdrsTotal <= pGso->offHdr2 ))
+ return false;
+
+ /* min size of the 1st header(s). */
+ switch (enmType)
+ {
+ case PDMNETWORKGSOTYPE_IPV4_TCP:
+ case PDMNETWORKGSOTYPE_IPV4_UDP:
+ if (RT_UNLIKELY( (unsigned)pGso->offHdr2 - pGso->offHdr1 < RTNETIPV4_MIN_LEN ))
+ return false;
+ break;
+ case PDMNETWORKGSOTYPE_IPV6_TCP:
+ case PDMNETWORKGSOTYPE_IPV6_UDP:
+ if (RT_UNLIKELY( (unsigned)pGso->offHdr2 - pGso->offHdr1 < RTNETIPV6_MIN_LEN ))
+ return false;
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
+ if (RT_UNLIKELY( (unsigned)pGso->offHdr2 - pGso->offHdr1 < RTNETIPV4_MIN_LEN + RTNETIPV6_MIN_LEN ))
+ return false;
+ break;
+ case PDMNETWORKGSOTYPE_INVALID:
+ case PDMNETWORKGSOTYPE_END:
+ break;
+ /* no default case! want gcc warnings. */
+ }
+
+ /* min size of the 2nd header. */
+ switch (enmType)
+ {
+ case PDMNETWORKGSOTYPE_IPV4_TCP:
+ case PDMNETWORKGSOTYPE_IPV6_TCP:
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
+ if (RT_UNLIKELY( (unsigned)pGso->cbHdrsTotal - pGso->offHdr2 < RTNETTCP_MIN_LEN ))
+ return false;
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_UDP:
+ case PDMNETWORKGSOTYPE_IPV6_UDP:
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
+ if (RT_UNLIKELY( (unsigned)pGso->cbHdrsTotal - pGso->offHdr2 < RTNETUDP_MIN_LEN ))
+ return false;
+ break;
+ case PDMNETWORKGSOTYPE_INVALID:
+ case PDMNETWORKGSOTYPE_END:
+ break;
+ /* no default case! want gcc warnings. */
+ }
+
+ /* There must be at more than one segment. */
+ if (RT_UNLIKELY( cbFrame <= pGso->cbHdrsTotal ))
+ return false;
+ if (RT_UNLIKELY( cbFrame - pGso->cbHdrsTotal < pGso->cbMaxSeg ))
+ return false;
+
+ return true;
+}
+
+
+/**
+ * Returns the length of header for a particular segment/fragment.
+ *
+ * We cannot simply treat UDP header as a part of payload because we do not
+ * want to modify the payload but still need to modify the checksum field in
+ * UDP header. So we want to include UDP header when calculating the length
+ * of headers in the first segment getting it copied to a temporary buffer
+ * along with other headers.
+ *
+ * @returns Length of headers (including UDP header for the first fragment).
+ * @param pGso The GSO context.
+ * @param iSeg The segment index.
+ */
+DECLINLINE(uint8_t) pdmNetSegHdrLen(PCPDMNETWORKGSO pGso, uint32_t iSeg)
+{
+ return iSeg ? pGso->cbHdrsSeg : pGso->cbHdrsTotal;
+}
+
+/**
+ * Returns the length of payload for a particular segment/fragment.
+ *
+ * The first segment does not contain UDP header. The size of UDP header is
+ * determined as the difference between the total headers size and the size
+ * used during segmentation.
+ *
+ * @returns Length of payload (including UDP header for the first fragment).
+ * @param pGso The GSO context.
+ * @param iSeg The segment that we're carving out (0-based).
+ * @param cSegs The number of segments in the GSO frame.
+ * @param cbFrame The size of the GSO frame.
+ */
+DECLINLINE(uint32_t) pdmNetSegPayloadLen(PCPDMNETWORKGSO pGso, uint32_t iSeg, uint32_t cSegs, uint32_t cbFrame)
+{
+ if (iSeg + 1 == cSegs)
+ return cbFrame - iSeg * pGso->cbMaxSeg - pdmNetSegHdrLen(pGso, iSeg);
+ else
+ return pGso->cbMaxSeg - (iSeg ? 0 : pGso->cbHdrsTotal - pGso->cbHdrsSeg);
+}
+
+/**
+ * Calculates the number of segments a GSO frame will be segmented into.
+ *
+ * @returns Segment count.
+ * @param pGso The GSO context.
+ * @param cbFrame The GSO frame size (header proto + payload).
+ */
+DECLINLINE(uint32_t) PDMNetGsoCalcSegmentCount(PCPDMNETWORKGSO pGso, size_t cbFrame)
+{
+ size_t cbPayload;
+ Assert(PDMNetGsoIsValid(pGso, sizeof(*pGso), cbFrame));
+ cbPayload = cbFrame - pGso->cbHdrsSeg;
+ return (uint32_t)((cbPayload + pGso->cbMaxSeg - 1) / pGso->cbMaxSeg);
+}
+
+
+/**
+ * Used to find the IPv6 header when handling 4to6 tunneling.
+ *
+ * @returns Offset of the IPv6 header.
+ * @param pbSegHdrs The headers / frame start.
+ * @param offIpHdr The offset of the IPv4 header.
+ */
+DECLINLINE(uint8_t) pgmNetGsoCalcIpv6Offset(uint8_t *pbSegHdrs, uint8_t offIPv4Hdr)
+{
+ PCRTNETIPV4 pIPv4Hdr = (PCRTNETIPV4)&pbSegHdrs[offIPv4Hdr];
+ return offIPv4Hdr + pIPv4Hdr->ip_hl * 4;
+}
+
+
+/**
+ * Update an UDP header after carving out a segment
+ *
+ * @param u32PseudoSum The pseudo checksum.
+ * @param pbSegHdrs Pointer to the header bytes / frame start.
+ * @param offUdpHdr The offset into @a pbSegHdrs of the UDP header.
+ * @param pbPayload Pointer to the payload bytes.
+ * @param cbPayload The amount of payload.
+ * @param cbHdrs The size of all the headers.
+ * @param enmCsumType Whether to checksum the payload, the pseudo
+ * header or nothing.
+ * @internal
+ */
+DECLINLINE(void) pdmNetGsoUpdateUdpHdr(uint32_t u32PseudoSum, uint8_t *pbSegHdrs, uint8_t offUdpHdr,
+ uint8_t const *pbPayload, uint32_t cbPayload, uint8_t cbHdrs,
+ PDMNETCSUMTYPE enmCsumType)
+{
+ PRTNETUDP pUdpHdr = (PRTNETUDP)&pbSegHdrs[offUdpHdr];
+ pUdpHdr->uh_ulen = RT_H2N_U16(cbPayload + cbHdrs - offUdpHdr);
+ switch (enmCsumType)
+ {
+ case PDMNETCSUMTYPE_NONE:
+ pUdpHdr->uh_sum = 0;
+ break;
+ case PDMNETCSUMTYPE_COMPLETE:
+ pUdpHdr->uh_sum = RTNetUDPChecksum(u32PseudoSum, pUdpHdr);
+ break;
+ case PDMNETCSUMTYPE_PSEUDO:
+ pUdpHdr->uh_sum = ~RTNetIPv4FinalizeChecksum(u32PseudoSum);
+ break;
+ default:
+ NOREF(pbPayload);
+ AssertFailed();
+ break;
+ }
+}
+
+
+/**
+ * Update an UDP header after carving out an IP fragment
+ *
+ * @param u32PseudoSum The pseudo checksum.
+ * @param pbSegHdrs Pointer to the header bytes copy
+ * @param pbFrame Pointer to the frame start.
+ * @param offUdpHdr The offset into @a pbSegHdrs of the UDP header.
+ *
+ * @internal
+ */
+DECLINLINE(void) pdmNetGsoUpdateUdpHdrUfo(uint32_t u32PseudoSum, uint8_t *pbSegHdrs, const uint8_t *pbFrame, uint8_t offUdpHdr)
+{
+ PCRTNETUDP pcUdpHdrOrig = (PCRTNETUDP)&pbFrame[offUdpHdr];
+ PRTNETUDP pUdpHdr = (PRTNETUDP)&pbSegHdrs[offUdpHdr];
+ pUdpHdr->uh_sum = RTNetUDPChecksum(u32PseudoSum, pcUdpHdrOrig);
+}
+
+
+/**
+ * Update a TCP header after carving out a segment.
+ *
+ * @param u32PseudoSum The pseudo checksum.
+ * @param pbSegHdrs Pointer to the header bytes / frame start.
+ * @param offTcpHdr The offset into @a pbSegHdrs of the TCP header.
+ * @param pbPayload Pointer to the payload bytes.
+ * @param cbPayload The amount of payload.
+ * @param offPayload The offset into the payload that we're splitting
+ * up. We're ASSUMING that the payload follows
+ * immediately after the TCP header w/ options.
+ * @param cbHdrs The size of all the headers.
+ * @param fLastSeg Set if this is the last segment.
+ * @param enmCsumType Whether to checksum the payload, the pseudo
+ * header or nothing.
+ * @internal
+ */
+DECLINLINE(void) pdmNetGsoUpdateTcpHdr(uint32_t u32PseudoSum, uint8_t *pbSegHdrs, uint8_t offTcpHdr,
+ uint8_t const *pbPayload, uint32_t cbPayload, uint32_t offPayload, uint8_t cbHdrs,
+ bool fLastSeg, PDMNETCSUMTYPE enmCsumType)
+{
+ PRTNETTCP pTcpHdr = (PRTNETTCP)&pbSegHdrs[offTcpHdr];
+ pTcpHdr->th_seq = RT_H2N_U32(RT_N2H_U32(pTcpHdr->th_seq) + offPayload);
+ if (!fLastSeg)
+ pTcpHdr->th_flags &= ~(RTNETTCP_F_FIN | RTNETTCP_F_PSH);
+ switch (enmCsumType)
+ {
+ case PDMNETCSUMTYPE_NONE:
+ pTcpHdr->th_sum = 0;
+ break;
+ case PDMNETCSUMTYPE_COMPLETE:
+ pTcpHdr->th_sum = RTNetTCPChecksum(u32PseudoSum, pTcpHdr, pbPayload, cbPayload);
+ break;
+ case PDMNETCSUMTYPE_PSEUDO:
+ pTcpHdr->th_sum = ~RTNetIPv4FinalizeChecksum(u32PseudoSum);
+ break;
+ default:
+ NOREF(cbHdrs);
+ AssertFailed();
+ break;
+ }
+}
+
+
+/**
+ * Updates a IPv6 header after carving out a segment.
+ *
+ * @returns 32-bit intermediary checksum value for the pseudo header.
+ * @param pbSegHdrs Pointer to the header bytes.
+ * @param offIpHdr The offset into @a pbSegHdrs of the IP header.
+ * @param cbSegPayload The amount of segmented payload. Not to be
+ * confused with the IP payload.
+ * @param cbHdrs The size of all the headers.
+ * @param offPktHdr Offset of the protocol packet header. For the
+ * pseudo header checksum calulation.
+ * @param bProtocol The protocol type. For the pseudo header.
+ * @internal
+ */
+DECLINLINE(uint32_t) pdmNetGsoUpdateIPv6Hdr(uint8_t *pbSegHdrs, uint8_t offIpHdr, uint32_t cbSegPayload, uint8_t cbHdrs,
+ uint8_t offPktHdr, uint8_t bProtocol)
+{
+ PRTNETIPV6 pIpHdr = (PRTNETIPV6)&pbSegHdrs[offIpHdr];
+ uint16_t cbPayload = (uint16_t)(cbHdrs - (offIpHdr + sizeof(RTNETIPV6)) + cbSegPayload);
+ pIpHdr->ip6_plen = RT_H2N_U16(cbPayload);
+ return RTNetIPv6PseudoChecksumEx(pIpHdr, bProtocol, (uint16_t)(cbHdrs - offPktHdr + cbSegPayload));
+}
+
+
+/**
+ * Updates a IPv4 header after carving out a segment.
+ *
+ * @returns 32-bit intermediary checksum value for the pseudo header.
+ * @param pbSegHdrs Pointer to the header bytes.
+ * @param offIpHdr The offset into @a pbSegHdrs of the IP header.
+ * @param cbSegPayload The amount of segmented payload.
+ * @param iSeg The segment index.
+ * @param cbHdrs The size of all the headers.
+ * @internal
+ */
+DECLINLINE(uint32_t) pdmNetGsoUpdateIPv4Hdr(uint8_t *pbSegHdrs, uint8_t offIpHdr, uint32_t cbSegPayload,
+ uint32_t iSeg, uint8_t cbHdrs)
+{
+ PRTNETIPV4 pIpHdr = (PRTNETIPV4)&pbSegHdrs[offIpHdr];
+ pIpHdr->ip_len = RT_H2N_U16(cbHdrs - offIpHdr + cbSegPayload);
+ pIpHdr->ip_id = RT_H2N_U16(RT_N2H_U16(pIpHdr->ip_id) + iSeg);
+ pIpHdr->ip_sum = RTNetIPv4HdrChecksum(pIpHdr);
+ return RTNetIPv4PseudoChecksum(pIpHdr);
+}
+
+
+/**
+ * Updates a IPv4 header after carving out an IP fragment.
+ *
+ * @param pbSegHdrs Pointer to the header bytes.
+ * @param offIpHdr The offset into @a pbSegHdrs of the IP header.
+ * @param cbSegPayload The amount of segmented payload.
+ * @param offFragment The offset of this fragment for reassembly.
+ * @param iSeg The segment index.
+ * @param cbHdrs The size of all the headers.
+ * @param fLastFragment True if this is the last fragment of datagram.
+ * @internal
+ */
+DECLINLINE(void) pdmNetGsoUpdateIPv4HdrUfo(uint8_t *pbSegHdrs, uint8_t offIpHdr, uint32_t cbSegPayload,
+ uint32_t offFragment, uint8_t cbHdrs, bool fLastFragment)
+{
+ PRTNETIPV4 pIpHdr = (PRTNETIPV4)&pbSegHdrs[offIpHdr];
+ pIpHdr->ip_len = RT_H2N_U16(cbHdrs - offIpHdr + cbSegPayload);
+ pIpHdr->ip_off = RT_H2N_U16((offFragment / 8) | (fLastFragment ? 0 : RTNETIPV4_FLAGS_MF));
+ pIpHdr->ip_sum = RTNetIPv4HdrChecksum(pIpHdr);
+}
+
+
+/**
+ * Carves out the specified segment in a destructive manner.
+ *
+ * This is for sequentially carving out segments and pushing them along for
+ * processing or sending. To avoid allocating a temporary buffer for
+ * constructing the segment in, we trash the previous frame by putting the
+ * header at the end of it.
+ *
+ * @returns Pointer to the segment frame that we've carved out.
+ * @param pGso The GSO context data.
+ * @param pbFrame Pointer to the GSO frame.
+ * @param cbFrame The size of the GSO frame.
+ * @param pbHdrScatch Pointer to a pGso->cbHdrs sized area where we
+ * can save the original header prototypes on the
+ * first call (@a iSeg is 0) and retrieve it on
+ * susequent calls. (Just use a 256 bytes
+ * buffer to make life easy.)
+ * @param iSeg The segment that we're carving out (0-based).
+ * @param cSegs The number of segments in the GSO frame. Use
+ * PDMNetGsoCalcSegmentCount to find this.
+ * @param pcbSegFrame Where to return the size of the returned segment
+ * frame.
+ */
+DECLINLINE(void *) PDMNetGsoCarveSegmentQD(PCPDMNETWORKGSO pGso, uint8_t *pbFrame, size_t cbFrame, uint8_t *pbHdrScatch,
+ uint32_t iSeg, uint32_t cSegs, uint32_t *pcbSegFrame)
+{
+ /*
+ * Figure out where the payload is and where the header starts before we
+ * do the protocol specific carving.
+ */
+ uint8_t * const pbSegHdrs = pbFrame + pGso->cbMaxSeg * iSeg;
+ uint8_t * const pbSegPayload = pbSegHdrs + pGso->cbHdrsSeg;
+ uint32_t const cbSegPayload = pdmNetSegPayloadLen(pGso, iSeg, cSegs, (uint32_t)cbFrame);
+ uint32_t const cbSegFrame = cbSegPayload + pGso->cbHdrsSeg;
+
+ /*
+ * Check assumptions (doing it after declaring the variables because of C).
+ */
+ Assert(iSeg < cSegs);
+ Assert(cSegs == PDMNetGsoCalcSegmentCount(pGso, cbFrame));
+ Assert(PDMNetGsoIsValid(pGso, sizeof(*pGso), cbFrame));
+
+ /*
+ * Copy the header and do the protocol specific massaging of it.
+ */
+ if (iSeg != 0)
+ memcpy(pbSegHdrs, pbHdrScatch, pGso->cbHdrsSeg);
+ else
+ memcpy(pbHdrScatch, pbSegHdrs, pGso->cbHdrsSeg); /* There is no need to save UDP header */
+
+ switch ((PDMNETWORKGSOTYPE)pGso->u8Type)
+ {
+ case PDMNETWORKGSOTYPE_IPV4_TCP:
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrsSeg),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ pGso->cbHdrsSeg, iSeg + 1 == cSegs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_UDP:
+ if (iSeg == 0)
+ pdmNetGsoUpdateUdpHdrUfo(RTNetIPv4PseudoChecksum((PRTNETIPV4)&pbFrame[pGso->offHdr1]),
+ pbSegHdrs, pbFrame, pGso->offHdr2);
+ pdmNetGsoUpdateIPv4HdrUfo(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ pdmNetSegHdrLen(pGso, iSeg), iSeg + 1 == cSegs);
+ break;
+ case PDMNETWORKGSOTYPE_IPV6_TCP:
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, pGso->cbHdrsSeg,
+ pGso->offHdr2, RTNETIPV4_PROT_TCP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ pGso->cbHdrsSeg, iSeg + 1 == cSegs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV6_UDP:
+ pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, pGso->cbHdrsSeg,
+ pGso->offHdr2, RTNETIPV4_PROT_UDP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrsSeg, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
+ pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrsSeg);
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pgmNetGsoCalcIpv6Offset(pbSegHdrs, pGso->offHdr1),
+ cbSegPayload, pGso->cbHdrsSeg, pGso->offHdr2, RTNETIPV4_PROT_TCP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ pGso->cbHdrsSeg, iSeg + 1 == cSegs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
+ pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, pGso->cbHdrsSeg);
+ pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pgmNetGsoCalcIpv6Offset(pbSegHdrs, pGso->offHdr1),
+ cbSegPayload, pGso->cbHdrsSeg, pGso->offHdr2, RTNETIPV4_PROT_UDP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, pGso->cbHdrsSeg, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_INVALID:
+ case PDMNETWORKGSOTYPE_END:
+ /* no default! wnat gcc warnings. */
+ break;
+ }
+
+ *pcbSegFrame = cbSegFrame;
+ return pbSegHdrs;
+}
+
+
+/**
+ * Carves out the specified segment in a non-destructive manner.
+ *
+ * The segment headers and segment payload is kept separate here. The GSO frame
+ * is still expected to be one linear chunk of data, but we don't modify any of
+ * it.
+ *
+ * @returns The offset into the GSO frame of the payload.
+ * @param pGso The GSO context data.
+ * @param pbFrame Pointer to the GSO frame. Used for retrieving
+ * the header prototype and for checksumming the
+ * payload. The buffer is not modified.
+ * @param cbFrame The size of the GSO frame.
+ * @param iSeg The segment that we're carving out (0-based).
+ * @param cSegs The number of segments in the GSO frame. Use
+ * PDMNetGsoCalcSegmentCount to find this.
+ * @param pbSegHdrs Where to return the headers for the segment
+ * that's been carved out. The buffer must be at
+ * least pGso->cbHdrs in size, using a 256 byte
+ * buffer is a recommended simplification.
+ * @param pcbSegHdrs Where to return the size of the returned
+ * segment headers.
+ * @param pcbSegPayload Where to return the size of the returned
+ * segment payload.
+ */
+DECLINLINE(uint32_t) PDMNetGsoCarveSegment(PCPDMNETWORKGSO pGso, const uint8_t *pbFrame, size_t cbFrame,
+ uint32_t iSeg, uint32_t cSegs, uint8_t *pbSegHdrs,
+ uint32_t *pcbSegHdrs, uint32_t *pcbSegPayload)
+{
+ /*
+ * Figure out where the payload is and where the header starts before we
+ * do the protocol specific carving.
+ */
+ uint32_t const cbSegHdrs = pdmNetSegHdrLen(pGso, iSeg);
+ uint8_t const * const pbSegPayload = pbFrame + cbSegHdrs + iSeg * pGso->cbMaxSeg;
+ uint32_t const cbSegPayload = pdmNetSegPayloadLen(pGso, iSeg, cSegs, (uint32_t)cbFrame);
+
+ /*
+ * Check assumptions (doing it after declaring the variables because of C).
+ */
+ Assert(iSeg < cSegs);
+ Assert(cSegs == PDMNetGsoCalcSegmentCount(pGso, cbFrame));
+ Assert(PDMNetGsoIsValid(pGso, sizeof(*pGso), cbFrame));
+
+ /*
+ * Copy the header and do the protocol specific massaging of it.
+ */
+ memcpy(pbSegHdrs, pbFrame, pGso->cbHdrsTotal); /* include UDP header */
+
+ switch ((PDMNETWORKGSOTYPE)pGso->u8Type)
+ {
+ case PDMNETWORKGSOTYPE_IPV4_TCP:
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, cbSegHdrs),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ cbSegHdrs, iSeg + 1 == cSegs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_UDP:
+ if (iSeg == 0)
+ pdmNetGsoUpdateUdpHdrUfo(RTNetIPv4PseudoChecksum((PRTNETIPV4)&pbFrame[pGso->offHdr1]),
+ pbSegHdrs, pbFrame, pGso->offHdr2);
+ pdmNetGsoUpdateIPv4HdrUfo(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ cbSegHdrs, iSeg + 1 == cSegs);
+ break;
+ case PDMNETWORKGSOTYPE_IPV6_TCP:
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, cbSegHdrs,
+ pGso->offHdr2, RTNETIPV4_PROT_TCP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ cbSegHdrs, iSeg + 1 == cSegs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV6_UDP:
+ pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, cbSegHdrs,
+ pGso->offHdr2, RTNETIPV4_PROT_UDP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, cbSegHdrs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
+ pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, cbSegHdrs);
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pgmNetGsoCalcIpv6Offset(pbSegHdrs, pGso->offHdr1),
+ cbSegPayload, cbSegHdrs, pGso->offHdr2, RTNETIPV4_PROT_TCP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, iSeg * pGso->cbMaxSeg,
+ cbSegHdrs, iSeg + 1 == cSegs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
+ pdmNetGsoUpdateIPv4Hdr(pbSegHdrs, pGso->offHdr1, cbSegPayload, iSeg, cbSegHdrs);
+ pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbSegHdrs, pgmNetGsoCalcIpv6Offset(pbSegHdrs, pGso->offHdr1),
+ cbSegPayload, cbSegHdrs, pGso->offHdr2, RTNETIPV4_PROT_UDP),
+ pbSegHdrs, pGso->offHdr2, pbSegPayload, cbSegPayload, cbSegHdrs, PDMNETCSUMTYPE_COMPLETE);
+ break;
+ case PDMNETWORKGSOTYPE_INVALID:
+ case PDMNETWORKGSOTYPE_END:
+ /* no default! wnat gcc warnings. */
+ break;
+ }
+
+ *pcbSegHdrs = cbSegHdrs;
+ *pcbSegPayload = cbSegPayload;
+ return cbSegHdrs + iSeg * pGso->cbMaxSeg;
+}
+
+
+/**
+ * Prepares the GSO frame for direct use without any segmenting.
+ *
+ * @param pGso The GSO context.
+ * @param pvFrame The frame to prepare.
+ * @param cbFrame The frame size.
+ * @param enmCsumType Whether to checksum the payload, the pseudo
+ * header or nothing.
+ */
+DECLINLINE(void) PDMNetGsoPrepForDirectUse(PCPDMNETWORKGSO pGso, void *pvFrame, size_t cbFrame, PDMNETCSUMTYPE enmCsumType)
+{
+ /*
+ * Figure out where the payload is and where the header starts before we
+ * do the protocol bits.
+ */
+ uint8_t * const pbHdrs = (uint8_t *)pvFrame;
+ uint8_t * const pbPayload = pbHdrs + pGso->cbHdrsTotal;
+ uint32_t const cbFrame32 = (uint32_t)cbFrame;
+ uint32_t const cbPayload = cbFrame32 - pGso->cbHdrsTotal;
+
+ /*
+ * Check assumptions (doing it after declaring the variables because of C).
+ */
+ Assert(PDMNetGsoIsValid(pGso, sizeof(*pGso), cbFrame));
+
+ /*
+ * Get down to busienss.
+ */
+ switch ((PDMNETWORKGSOTYPE)pGso->u8Type)
+ {
+ case PDMNETWORKGSOTYPE_IPV4_TCP:
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbFrame32 - pGso->cbHdrsTotal, 0, pGso->cbHdrsTotal),
+ pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrsTotal, true, enmCsumType);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_UDP:
+ pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbFrame32 - pGso->cbHdrsTotal, 0, pGso->cbHdrsTotal),
+ pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrsTotal, enmCsumType);
+ break;
+ case PDMNETWORKGSOTYPE_IPV6_TCP:
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pGso->offHdr1, cbPayload, pGso->cbHdrsTotal,
+ pGso->offHdr2, RTNETIPV4_PROT_TCP),
+ pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrsTotal, true, enmCsumType);
+ break;
+ case PDMNETWORKGSOTYPE_IPV6_UDP:
+ pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pGso->offHdr1, cbPayload, pGso->cbHdrsTotal,
+ pGso->offHdr2, RTNETIPV4_PROT_UDP),
+ pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrsTotal, enmCsumType);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP:
+ pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbPayload, 0, pGso->cbHdrsTotal);
+ pdmNetGsoUpdateTcpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pgmNetGsoCalcIpv6Offset(pbHdrs, pGso->offHdr1),
+ cbPayload, pGso->cbHdrsTotal, pGso->offHdr2, RTNETIPV4_PROT_TCP),
+ pbHdrs, pGso->offHdr2, pbPayload, cbPayload, 0, pGso->cbHdrsTotal, true, enmCsumType);
+ break;
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP:
+ pdmNetGsoUpdateIPv4Hdr(pbHdrs, pGso->offHdr1, cbPayload, 0, pGso->cbHdrsTotal);
+ pdmNetGsoUpdateUdpHdr(pdmNetGsoUpdateIPv6Hdr(pbHdrs, pgmNetGsoCalcIpv6Offset(pbHdrs, pGso->offHdr1),
+ cbPayload, pGso->cbHdrsTotal, pGso->offHdr2, RTNETIPV4_PROT_UDP),
+ pbHdrs, pGso->offHdr2, pbPayload, cbPayload, pGso->cbHdrsTotal, enmCsumType);
+ break;
+ case PDMNETWORKGSOTYPE_INVALID:
+ case PDMNETWORKGSOTYPE_END:
+ /* no default! wnat gcc warnings. */
+ break;
+ }
+}
+
+
+/**
+ * Gets the GSO type name string.
+ *
+ * @returns Pointer to read only name string.
+ * @param enmType The type.
+ */
+DECLINLINE(const char *) PDMNetGsoTypeName(PDMNETWORKGSOTYPE enmType)
+{
+ switch (enmType)
+ {
+ case PDMNETWORKGSOTYPE_IPV4_TCP: return "TCPv4";
+ case PDMNETWORKGSOTYPE_IPV6_TCP: return "TCPv6";
+ case PDMNETWORKGSOTYPE_IPV4_UDP: return "UDPv4";
+ case PDMNETWORKGSOTYPE_IPV6_UDP: return "UDPv6";
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_TCP: return "4to6TCP";
+ case PDMNETWORKGSOTYPE_IPV4_IPV6_UDP: return "4to6UDP";
+ case PDMNETWORKGSOTYPE_INVALID: return "invalid";
+ case PDMNETWORKGSOTYPE_END: return "end";
+ }
+ return "bad-gso-type";
+}
+
diff --git a/include/VBox/vmm/pdmnetshaper.h b/include/VBox/vmm/pdmnetshaper.h
new file mode 100644
index 00000000..b2aa5bab
--- /dev/null
+++ b/include/VBox/vmm/pdmnetshaper.h
@@ -0,0 +1,120 @@
+/** @file
+ * PDM - Pluggable Device Manager, Network Shaper.
+ */
+
+/*
+ * Copyright (C) 2011-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmnetshaper_h
+#define ___VBox_vmm_pdmnetshaper_h
+
+#include <VBox/types.h>
+#include <VBox/err.h>
+#include <VBox/vmm/pdmnetifs.h>
+#include <iprt/assert.h>
+#include <iprt/sg.h>
+
+
+#define PDM_NETSHAPER_MIN_BUCKET_SIZE 65536 /* bytes */
+#define PDM_NETSHAPER_MAX_LATENCY 100 /* milliseconds */
+
+RT_C_DECLS_BEGIN
+
+typedef struct PDMNSFILTER
+{
+ /** [R3] Pointer to the next group in the list. */
+ struct PDMNSFILTER *pNext;
+ /** [R3] Pointer to the bandwidth group. */
+ struct PDMNSBWGROUP *pBwGroupR3;
+ /** [R0] Pointer to the bandwidth group. */
+ R0PTRTYPE(struct PDMNSBWGROUP *) pBwGroupR0;
+ /** Becomes true when filter fails to obtain bandwidth. */
+ bool fChoked;
+ /** [R3] The driver this filter is aggregated into. */
+ PPDMINETWORKDOWN pIDrvNet;
+} PDMNSFILTER;
+
+/** @defgroup grp_pdm_net_shaper The PDM Network Shaper API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/** Pointer to a PDM filter handle. */
+typedef struct PDMNSFILTER *PPDMNSFILTER;
+/** Pointer to a network shaper. */
+typedef struct PDMNETSHAPER *PPDMNETSHAPER;
+
+
+/**
+ * Obtain bandwidth in a bandwidth group (R0 version).
+ *
+ * @returns VBox status code.
+ * @param pFilter Pointer to the filter that allocates bandwidth.
+ * @param cbTransfer Number of bytes to allocate.
+ */
+VMMR0DECL(bool) PDMR0NsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer);
+
+/**
+ * Obtain bandwidth in a bandwidth group.
+ *
+ * @returns VBox status code.
+ * @param pFilter Pointer to the filter that allocates bandwidth.
+ * @param cbTransfer Number of bytes to allocate.
+ */
+VMMR3DECL(bool) PDMR3NsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer);
+
+/**
+ * Attach network filter driver from bandwidth group.
+ *
+ * @returns VBox status code.
+ * @param pVM Handle of VM.
+ * @param pDrvIns The driver instance.
+ * @param pcszBwGroup Name of the bandwidth group to attach to.
+ * @param pFilter Pointer to the filter we attach.
+ */
+VMMR3DECL(int) PDMR3NsAttach(PVM pVM, PPDMDRVINS pDrvIns, const char *pcszBwGroup, PPDMNSFILTER pFilter);
+
+/**
+ * Detach network filter driver from bandwidth group.
+ *
+ * @returns VBox status code.
+ * @param pVM Handle of VM.
+ * @param pDrvIns The driver instance.
+ * @param pFilter Pointer to the filter we detach.
+ */
+VMMR3DECL(int) PDMR3NsDetach(PVM pVM, PPDMDRVINS pDrvIns, PPDMNSFILTER pFilter);
+
+/**
+ * Adjusts the maximum rate for the bandwidth group.
+ *
+ * @returns VBox status code.
+ * @param pVM Handle of VM.
+ * @param pcszBwGroup Name of the bandwidth group to attach to.
+ * @param cbTransferPerSecMax Maximum number of bytes per second to be transmitted.
+ */
+VMMR3DECL(int) PDMR3NsBwGroupSetLimit(PVM pVM, const char *pcszBwGroup, uint64_t cbTransferPerSecMax);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/pdmnetshaperint.h b/include/VBox/vmm/pdmnetshaperint.h
new file mode 100644
index 00000000..3bbfcda7
--- /dev/null
+++ b/include/VBox/vmm/pdmnetshaperint.h
@@ -0,0 +1,94 @@
+/* $Id: pdmnetshaperint.h $ */
+/** @file
+ * PDM Network Shaper - Internal data structures and functions common for both
+ * R0 and R3 parts.
+ */
+
+/*
+ * Copyright (C) 2011-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+/**
+ * Bandwidth group instance data
+ */
+typedef struct PDMNSBWGROUP
+{
+ /** Pointer to the next group in the list. */
+ struct PDMNSBWGROUP *pNext;
+ /** Pointer to the shared UVM structure. */
+ struct PDMNETSHAPER *pShaper;
+ /** Critical section protecting all members below. */
+ PDMCRITSECT cs;
+ /** Pointer to the first filter attached to this group. */
+ struct PDMNSFILTER *pFiltersHead;
+ /** Bandwidth group name. */
+ char *pszName;
+ /** Maximum number of bytes filters are allowed to transfer. */
+ volatile uint64_t cbTransferPerSecMax;
+ /** Number of bytes we are allowed to transfer in one burst. */
+ volatile uint32_t cbBucketSize;
+ /** Number of bytes we were allowed to transfer at the last update. */
+ volatile uint32_t cbTokensLast;
+ /** Timestamp of the last update */
+ volatile uint64_t tsUpdatedLast;
+ /** Reference counter - How many filters are associated with this group. */
+ volatile uint32_t cRefs;
+} PDMNSBWGROUP;
+/** Pointer to a bandwidth group. */
+typedef PDMNSBWGROUP *PPDMNSBWGROUP;
+
+DECLINLINE(bool) pdmNsAllocateBandwidth(PPDMNSFILTER pFilter, size_t cbTransfer)
+{
+ AssertPtrReturn(pFilter, true);
+ if (!VALID_PTR(pFilter->CTX_SUFF(pBwGroup)))
+ return true;
+
+ PPDMNSBWGROUP pBwGroup = ASMAtomicReadPtrT(&pFilter->CTX_SUFF(pBwGroup), PPDMNSBWGROUP);
+ int rc = PDMCritSectEnter(&pBwGroup->cs, VERR_SEM_BUSY); AssertRC(rc);
+ if (RT_UNLIKELY(rc == VERR_SEM_BUSY))
+ return true;
+ bool fAllowed = true;
+ if (pBwGroup->cbTransferPerSecMax)
+ {
+ /* Re-fill the bucket first */
+ uint64_t tsNow = RTTimeSystemNanoTS();
+ uint32_t uTokensAdded = (tsNow - pBwGroup->tsUpdatedLast)*pBwGroup->cbTransferPerSecMax/(1000*1000*1000);
+ uint32_t uTokens = RT_MIN(pBwGroup->cbBucketSize, uTokensAdded + pBwGroup->cbTokensLast);
+
+ if (cbTransfer > uTokens)
+ {
+ fAllowed = false;
+ ASMAtomicWriteBool(&pFilter->fChoked, true);
+ }
+ else
+ {
+ pBwGroup->tsUpdatedLast = tsNow;
+ pBwGroup->cbTokensLast = uTokens - (uint32_t)cbTransfer;
+ }
+ Log2((LOG_FN_FMT "BwGroup=%#p{%s} cbTransfer=%u uTokens=%u uTokensAdded=%u fAllowed=%RTbool\n",
+ __PRETTY_FUNCTION__, pBwGroup, pBwGroup->pszName, cbTransfer, uTokens, uTokensAdded, fAllowed));
+ }
+ else
+ Log2((LOG_FN_FMT "BwGroup=%#p{%s} disabled fAllowed=%RTbool\n",
+ __PRETTY_FUNCTION__, pBwGroup, pBwGroup->pszName, fAllowed));
+
+ rc = PDMCritSectLeave(&pBwGroup->cs); AssertRC(rc);
+ return fAllowed;
+}
diff --git a/include/VBox/vmm/pdmnvram.h b/include/VBox/vmm/pdmnvram.h
new file mode 100644
index 00000000..10c1abc4
--- /dev/null
+++ b/include/VBox/vmm/pdmnvram.h
@@ -0,0 +1,70 @@
+/** @file
+ * PDM - Pluggable Device Manager, EFI NVRAM storage back-end.
+ */
+
+/*
+ * Copyright (C) 2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmnvram_h_
+#define ___VBox_vmm_pdmnvram_h_
+
+#include <VBox/types.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_ifs_nvram NVRAM Interface
+ * @ingroup grp_pdm_interfaces
+ * @{
+ */
+
+typedef struct PDMINVRAM *PPDMINVRAM;
+
+typedef struct PDMINVRAM
+{
+ /**
+ * This method flushes all values in the storage.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnFlushNvramStorage, (PPDMINVRAM pInterface));
+
+ /**
+ * This method store NVRAM variable to storage
+ */
+ DECLR3CALLBACKMEMBER(int, pfnStoreNvramValue, (PPDMINVRAM pInterface, int idxVariable, RTUUID *pVendorUuid, const char *pcszVariableName, size_t cbVariableName, uint8_t *pu8Value, size_t cbValue));
+
+ /**
+ * This method load NVRAM variable to storage
+ */
+ DECLR3CALLBACKMEMBER(int, pfnLoadNvramValue, (PPDMINVRAM pInterface, int idxVariable, RTUUID *pVendorUuid, char *pcszVariableName, size_t *pcbVariableName, uint8_t *pu8Value, size_t *pcbValue));
+
+} PDMINVRAM;
+
+
+#define PDMINVRAM_IID "11226408-CB4C-4369-9218-1EE0092FB9F8"
+
+/** @} */
+
+RT_C_DECLS_END
+
+
+#endif
+
+
diff --git a/include/VBox/vmm/pdmpci.h b/include/VBox/vmm/pdmpci.h
new file mode 100644
index 00000000..16d925f1
--- /dev/null
+++ b/include/VBox/vmm/pdmpci.h
@@ -0,0 +1,398 @@
+/** @file
+ * PDM - Pluggable Device Manager, raw PCI Devices. (VMM)
+ */
+
+/*
+ * Copyright (C) 2010-2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmpci_h
+#define ___VBox_vmm_pdmpci_h
+
+#include <VBox/types.h>
+#include <VBox/rawpci.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_pcidev The raw PCI Devices API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+typedef struct PDMIPCIRAW *PPDMIPCIRAW;
+typedef struct PDMIPCIRAW
+{
+ /**
+ * Notify virtual device that interrupt has arrived.
+ * For this callback to be called, interface have to be
+ * registered with PDMIPCIRAWUP::pfnRegisterInterruptListener.
+ *
+ * @note no level parameter, as we can only support flip-flop.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param iGuestIrq Guest interrupt number, passed earlier when registering listener.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnInterruptRequest ,(PPDMIPCIRAW pInterface, int32_t iGuestIrq));
+} PDMIPCIRAW;
+
+typedef struct PDMIPCIRAWUP *PPDMIPCIRAWUP;
+typedef struct PDMIPCIRAWUP
+{
+ /**
+ * Host PCI MMIO access function.
+ */
+
+ /**
+ * Request driver info about PCI region on host PCI device.
+ *
+ * @returns true, if region is present, and out parameters are correct
+ * @param pInterface Pointer to this interface structure.
+ * @param iRegion Region number.
+ * @param pRegStart Where to store region base address (guest).
+ * @param piRegSize Where to store region size.
+ *
+ * @param fMmio If region is MMIO or IO.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnGetRegionInfo, (PPDMIPCIRAWUP pInterface,
+ int32_t iRegion,
+ RTGCPHYS *pRegStart,
+ uint64_t *piRegSize,
+ uint32_t *pfFlags
+ ));
+
+ /**
+ * Request driver to map part of host device's MMIO region to the VM process and maybe kernel.
+ * Shall only be issued within earlier obtained with pfnGetRegionInfo()
+ * host physical address ranges for the device BARs. Even if failed, device still may function
+ * using pfnMmio* and pfnPio* operations, just much slower.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param iRegion Number of the region.
+ * @param StartAddress Host physical address of start.
+ * @param iRegionSize Size of the region.
+ * @param fFlags Flags, currently lowest significant bit set if R0 mapping requested too
+ * @param ppvAddressR3 Where to store mapped region address for R3 (can be 0, if cannot map into userland)
+ * @param ppvAddressR0 Where to store mapped region address for R0 (can be 0, if cannot map into kernel)
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMapRegion, (PPDMIPCIRAWUP pInterface,
+ int32_t iRegion,
+ RTHCPHYS StartAddress,
+ uint64_t iRegionSize,
+ uint32_t fFlags,
+ RTR3PTR *ppvAddressR3,
+ RTR0PTR *ppvAddressR0
+ ));
+
+ /**
+ * Request driver to unmap part of host device's MMIO region to the VM process.
+ * Shall only be issued with pointer earlier obtained with pfnMapRegion().
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure
+ * @param iRegion Number of the region.
+ * @param StartAddress Host physical address of start.
+ * @param iRegionSize Size of the region.
+ * @param pvAddressR3 R3 address of mapped region.
+ * @param pvAddressR0 R0 address of mapped region.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUnmapRegion, (PPDMIPCIRAWUP pInterface,
+ int iRegion,
+ RTHCPHYS StartAddress,
+ uint64_t iRegionSize,
+ RTR3PTR pvAddressR3,
+ RTR0PTR pvAddressR0
+ ));
+
+ /**
+ * Request port IO write.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param iPort IO port.
+ * @param iValue Value to write.
+ * @param cb Access width.
+ *
+ * @thread EMT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPioWrite, (PPDMIPCIRAWUP pInterface,
+ uint16_t iPort,
+ uint32_t iValue,
+ unsigned cb
+ ));
+
+ /**
+ * Request port IO read.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param iPort IO port.
+ * @param piValue Place to store read value.
+ * @param cb Access width.
+ *
+ * @thread EMT thread.
+ */
+
+ DECLR3CALLBACKMEMBER(int, pfnPioRead, (PPDMIPCIRAWUP pInterface,
+ uint16_t iPort,
+ uint32_t *piValue,
+ unsigned cb
+ ));
+
+
+ /**
+ * Request MMIO write. This callback is only called if driver wants to receive MMIO via
+ * pu32Flags argument of pfnPciDeviceConstructStart().
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param Address Guest physical address.
+ * @param pValue Address of value to write.
+ * @param cb Access width.
+ *
+ * @thread EMT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnMmioWrite, (PPDMIPCIRAWUP pInterface,
+ RTR0PTR Address,
+ void const *pValue,
+ unsigned cb
+ ));
+
+ /**
+ * Request MMIO read.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param Address Guest physical address.
+ * @param pValue Place to store read value.
+ * @param cb Access width.
+ *
+ * @thread EMT thread.
+ */
+
+ DECLR3CALLBACKMEMBER(int, pfnMmioRead, (PPDMIPCIRAWUP pInterface,
+ RTR0PTR Address,
+ void *pValue,
+ unsigned cb
+ ));
+
+ /**
+ * Host PCI config space accessors.
+ */
+ /**
+ * Request driver to write value to host device's PCI config space.
+ * Host specific way (PIO or MCFG) is used to perform actual operation.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param iOffset Offset in PCI config space.
+ * @param iValue Value to write.
+ * @param cb Access width.
+ *
+ * @thread EMT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPciCfgWrite, (PPDMIPCIRAWUP pInterface,
+ uint32_t iOffset,
+ void* pValue,
+ unsigned cb
+ ));
+ /**
+ * Request driver to read value from host device's PCI config space.
+ * Host specific way (PIO or MCFG) is used to perform actual operation.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param iOffset Offset in PCI config space.
+ * @param pValue Where to store read value.
+ * @param cb Access width.
+ *
+ * @thread EMT thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPciCfgRead, (PPDMIPCIRAWUP pInterface,
+ uint32_t iOffset,
+ void *pValue,
+ unsigned cb ));
+
+ /**
+ * Request to enable interrupt notifications. Please note that this is purely
+ * R3 interface, so it's up to implementor to perform necessary machinery
+ * for communications with host OS kernel driver. Typical implementation will start
+ * userland thread waiting on shared semaphore (such as using SUPSEMEVENT),
+ * notified by the kernel interrupt handler, and then will call
+ * upper port pfnInterruptRequest() based on data provided by the driver.
+ * This apporach is taken, as calling VBox code from an asyncronous R0
+ * interrupt handler when VMM may not be even running doesn't look
+ * like a good idea.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param pListener Pointer to the listener object.
+ * @param iGuestIrq Guest IRQ to be passed to pfnInterruptRequest().
+ *
+ * @thread Any thread, pfnInterruptRequest() will be usually invoked on a dedicated thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnEnableInterruptNotifications, (PPDMIPCIRAWUP pInterface, int32_t iGuestIrq
+ ));
+
+ /**
+ * Request to disable interrupt notifications.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDisableInterruptNotifications, (PPDMIPCIRAWUP pInterface
+ ));
+
+ /**
+ * Notification APIs.
+ */
+
+ /**
+ * Notify driver when raw PCI device construction starts. Have to be the first operation
+ * as initializes internal state and opens host device driver.
+ *
+ * @returns status code
+ * @param pInterface Pointer to this interface structure.
+ * @param iHostAddress Host PCI address of device attached.
+ * @param iGuestAddress Guest PCI address of device attached.
+ * @param szDeviceName Human readable device name.
+ * @param fDeviceFlags Flags for the host device.
+ * @param pu32Flags Flags for virtual device, from the upper driver.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPciDeviceConstructStart, (PPDMIPCIRAWUP pInterface,
+ uint32_t iHostAddress,
+ uint32_t iGuestAddress,
+ const char* szDeviceName,
+ uint32_t fDeviceFlags,
+ uint32_t *pu32Flags));
+
+ /**
+ * Notify driver when raw PCI device construction completes, so that it may
+ * perform further actions depending on success or failure of this operation.
+ * Standard action is to raise global IHostPciDevicePlugEvent.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param rc Result code of the operation.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnPciDeviceConstructComplete, (PPDMIPCIRAWUP pInterface,
+ int rc));
+
+ /**
+ * Notify driver on finalization of raw PCI device.
+ *
+ * @param pInterface Pointer to this interface structure.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPciDeviceDestruct, (PPDMIPCIRAWUP pInterface,
+ uint32_t fFlags));
+
+ /**
+ * Notify driver on guest power state change.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param aState New power state.
+ * @param pu64Param State-specific in/out parameter. For now only used during power-on to provide VM caps.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPciDevicePowerStateChange, (PPDMIPCIRAWUP pInterface,
+ PCIRAWPOWERSTATE aState,
+ uint64_t *pu64Param));
+
+ /**
+ * Notify driver about runtime error.
+ *
+ * @param pInterface Pointer to this interface structure.
+ * @param fFatal If error is fatal.
+ * @param szErrorId Error ID.
+ * @param szMessage Error message.
+ *
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnReportRuntimeError, (PPDMIPCIRAWUP pInterface,
+ uint8_t fFatal,
+ const char* szErrorId,
+ const char* szMessage));
+} PDMIPCIRAWUP;
+
+/**
+ * Init R0 PCI module.
+ */
+PCIRAWR0DECL(int) PciRawR0Init(void);
+/**
+ * Process request (in R0).
+ */
+PCIRAWR0DECL(int) PciRawR0ProcessReq(PSUPDRVSESSION pSession, PVM pVM, PPCIRAWSENDREQ pReq);
+/**
+ * Terminate R0 PCI module.
+ */
+PCIRAWR0DECL(void) PciRawR0Term(void);
+
+/**
+ * Per-VM R0 module init.
+ */
+PCIRAWR0DECL(int) PciRawR0InitVM(PVM pVM);
+
+/**
+ * Per-VM R0 module termination routine.
+ */
+PCIRAWR0DECL(void) PciRawR0TermVM(PVM pVM);
+
+/**
+ * Flags returned by pfnPciDeviceConstructStart(), to notify device
+ * how it shall handle device IO traffic.
+ */
+typedef enum PCIRAWDEVICEFLAGS
+{
+ /** Intercept port IO (R3 PIO always go to the driver). */
+ PCIRAWRFLAG_CAPTURE_PIO = (1 << 0),
+ /** Intercept MMIO. */
+ PCIRAWRFLAG_CAPTURE_MMIO = (1 << 1),
+ /** Allow bus mastering by physical device (requires IOMMU). */
+ PCIRAWRFLAG_ALLOW_BM = (1 << 2),
+ /** Allow R3 MMIO mapping. */
+ PCIRAWRFLAG_ALLOW_R3MAP = (1 << 3),
+
+ /** The usual 32-bit type blow up. */
+ PCIRAWRFLAG_32BIT_HACK = 0x7fffffff
+} PCIRAWDEVICEFLAGS;
+
+#define PDMIPCIRAWUP_IID "06daa17f-097b-4ebe-a626-15f467b1de12"
+#define PDMIPCIRAW_IID "68c6e4c4-4223-47e0-9134-e3c297992543"
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
diff --git a/include/VBox/vmm/pdmqueue.h b/include/VBox/vmm/pdmqueue.h
new file mode 100644
index 00000000..3445c85a
--- /dev/null
+++ b/include/VBox/vmm/pdmqueue.h
@@ -0,0 +1,147 @@
+/** @file
+ * PDM - Pluggable Device Manager, Queues.
+ */
+
+/*
+ * Copyright (C) 2006-2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmqueue_h
+#define ___VBox_vmm_pdmqueue_h
+
+#include <VBox/types.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_queue The PDM Queues API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/** Pointer to a PDM queue. Also called PDM queue handle. */
+typedef struct PDMQUEUE *PPDMQUEUE;
+
+/** Pointer to a PDM queue item core. */
+typedef struct PDMQUEUEITEMCORE *PPDMQUEUEITEMCORE;
+
+/**
+ * PDM queue item core.
+ */
+typedef struct PDMQUEUEITEMCORE
+{
+ /** Pointer to the next item in the pending list - R3 Pointer. */
+ R3PTRTYPE(PPDMQUEUEITEMCORE) pNextR3;
+ /** Pointer to the next item in the pending list - R0 Pointer. */
+ R0PTRTYPE(PPDMQUEUEITEMCORE) pNextR0;
+ /** Pointer to the next item in the pending list - RC Pointer. */
+ RCPTRTYPE(PPDMQUEUEITEMCORE) pNextRC;
+#if HC_ARCH_BITS == 64
+ RTRCPTR Alignment0;
+#endif
+} PDMQUEUEITEMCORE;
+
+
+/**
+ * Queue consumer callback for devices.
+ *
+ * @returns Success indicator.
+ * If false the item will not be removed and the flushing will stop.
+ * @param pDevIns The device instance.
+ * @param pItem The item to consume. Upon return this item will be freed.
+ */
+typedef DECLCALLBACK(bool) FNPDMQUEUEDEV(PPDMDEVINS pDevIns, PPDMQUEUEITEMCORE pItem);
+/** Pointer to a FNPDMQUEUEDEV(). */
+typedef FNPDMQUEUEDEV *PFNPDMQUEUEDEV;
+
+/**
+ * Queue consumer callback for USB devices.
+ *
+ * @returns Success indicator.
+ * If false the item will not be removed and the flushing will stop.
+ * @param pDevIns The USB device instance.
+ * @param pItem The item to consume. Upon return this item will be freed.
+ */
+typedef DECLCALLBACK(bool) FNPDMQUEUEUSB(PPDMUSBINS pUsbIns, PPDMQUEUEITEMCORE pItem);
+/** Pointer to a FNPDMQUEUEUSB(). */
+typedef FNPDMQUEUEUSB *PFNPDMQUEUEUSB;
+
+/**
+ * Queue consumer callback for drivers.
+ *
+ * @returns Success indicator.
+ * If false the item will not be removed and the flushing will stop.
+ * @param pDrvIns The driver instance.
+ * @param pItem The item to consume. Upon return this item will be freed.
+ */
+typedef DECLCALLBACK(bool) FNPDMQUEUEDRV(PPDMDRVINS pDrvIns, PPDMQUEUEITEMCORE pItem);
+/** Pointer to a FNPDMQUEUEDRV(). */
+typedef FNPDMQUEUEDRV *PFNPDMQUEUEDRV;
+
+/**
+ * Queue consumer callback for internal component.
+ *
+ * @returns Success indicator.
+ * If false the item will not be removed and the flushing will stop.
+ * @param pVM The VM handle.
+ * @param pItem The item to consume. Upon return this item will be freed.
+ */
+typedef DECLCALLBACK(bool) FNPDMQUEUEINT(PVM pVM, PPDMQUEUEITEMCORE pItem);
+/** Pointer to a FNPDMQUEUEINT(). */
+typedef FNPDMQUEUEINT *PFNPDMQUEUEINT;
+
+/**
+ * Queue consumer callback for external component.
+ *
+ * @returns Success indicator.
+ * If false the item will not be removed and the flushing will stop.
+ * @param pvUser User argument.
+ * @param pItem The item to consume. Upon return this item will be freed.
+ */
+typedef DECLCALLBACK(bool) FNPDMQUEUEEXT(void *pvUser, PPDMQUEUEITEMCORE pItem);
+/** Pointer to a FNPDMQUEUEEXT(). */
+typedef FNPDMQUEUEEXT *PFNPDMQUEUEEXT;
+
+#ifdef VBOX_IN_VMM
+VMMR3_INT_DECL(int) PDMR3QueueCreateDevice(PVM pVM, PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName, PPDMQUEUE *ppQueue);
+VMMR3_INT_DECL(int) PDMR3QueueCreateDriver(PVM pVM, PPDMDRVINS pDrvIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEDRV pfnCallback, const char *pszName, PPDMQUEUE *ppQueue);
+VMMR3_INT_DECL(int) PDMR3QueueCreateInternal(PVM pVM, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEINT pfnCallback, bool fGCEnabled, const char *pszName, PPDMQUEUE *ppQueue);
+VMMR3_INT_DECL(int) PDMR3QueueCreateExternal(PVM pVM, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEEXT pfnCallback, void *pvUser, const char *pszName, PPDMQUEUE *ppQueue);
+VMMR3_INT_DECL(int) PDMR3QueueDestroy(PPDMQUEUE pQueue);
+VMMR3_INT_DECL(int) PDMR3QueueDestroyDevice(PVM pVM, PPDMDEVINS pDevIns);
+VMMR3_INT_DECL(int) PDMR3QueueDestroyDriver(PVM pVM, PPDMDRVINS pDrvIns);
+VMMR3_INT_DECL(void) PDMR3QueueFlushAll(PVM pVM);
+#endif /* VBOX_IN_VMM */
+
+VMMDECL(PPDMQUEUEITEMCORE) PDMQueueAlloc(PPDMQUEUE pQueue);
+VMMDECL(void) PDMQueueInsert(PPDMQUEUE pQueue, PPDMQUEUEITEMCORE pItem);
+VMMDECL(void) PDMQueueInsertEx(PPDMQUEUE pQueue, PPDMQUEUEITEMCORE pItem, uint64_t NanoMaxDelay);
+VMMDECL(RCPTRTYPE(PPDMQUEUE)) PDMQueueRCPtr(PPDMQUEUE pQueue);
+VMMDECL(R0PTRTYPE(PPDMQUEUE)) PDMQueueR0Ptr(PPDMQUEUE pQueue);
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/pdmsrv.h b/include/VBox/vmm/pdmsrv.h
new file mode 100644
index 00000000..98766223
--- /dev/null
+++ b/include/VBox/vmm/pdmsrv.h
@@ -0,0 +1,335 @@
+/** @file
+ * PDM - Pluggable Device Manager, VM Services.
+ *
+ * @todo This has not been implemented, consider dropping the concept.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmsrv_h
+#define ___VBox_vmm_pdmsrv_h
+
+#include <VBox/vmm/pdmifs.h>
+#include <VBox/vmm/ssm.h>
+#include <VBox/vmm/cfgm.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_services The PDM Services API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/**
+ * Construct a service instance for a VM.
+ *
+ * @returns VBox status.
+ * @param pSrvIns The service instance data.
+ * If the registration structure is needed, pSrvIns->pReg points to it.
+ * @param pCfg Configuration node handle for the service. Use this to obtain the configuration
+ * of the driver instance. It's also found in pSrvIns->pCfg, but since it's primary
+ * usage is expected in this function it is passed as a parameter.
+ */
+typedef DECLCALLBACK(int) FNPDMSRVCONSTRUCT(PPDMSRVINS pSrvIns, PCFGMNODE pCfg);
+/** Pointer to a FNPDMSRVCONSTRUCT() function. */
+typedef FNPDMSRVCONSTRUCT *PFNPDMSRVCONSTRUCT;
+
+/**
+ * Destruct a driver instance.
+ *
+ * Most VM resources are freed by the VM. This callback is provided so that any non-VM
+ * resources can be freed correctly.
+ *
+ * @param pSrvIns The service instance data.
+ */
+typedef DECLCALLBACK(void) FNPDMSRVDESTRUCT(PPDMSRVINS pSrvIns);
+/** Pointer to a FNPDMSRVDESTRUCT() function. */
+typedef FNPDMSRVDESTRUCT *PFNPDMSRVDESTRUCT;
+
+/**
+ * Power On notification.
+ *
+ * @param pSrvIns The service instance data.
+ */
+typedef DECLCALLBACK(void) FNPDMSRVPOWERON(PPDMSRVINS pSrvIns);
+/** Pointer to a FNPDMSRVPOWERON() function. */
+typedef FNPDMSRVPOWERON *PFNPDMSRVPOWERON;
+
+/**
+ * Reset notification.
+ *
+ * @returns VBox status.
+ * @param pSrvIns The service instance data.
+ */
+typedef DECLCALLBACK(void) FNPDMSRVRESET(PPDMSRVINS pSrvIns);
+/** Pointer to a FNPDMSRVRESET() function. */
+typedef FNPDMSRVRESET *PFNPDMSRVRESET;
+
+/**
+ * Suspend notification.
+ *
+ * @returns VBox status.
+ * @param pSrvIns The service instance data.
+ */
+typedef DECLCALLBACK(void) FNPDMSRVSUSPEND(PPDMSRVINS pSrvIns);
+/** Pointer to a FNPDMSRVSUSPEND() function. */
+typedef FNPDMSRVSUSPEND *PFNPDMSRVSUSPEND;
+
+/**
+ * Resume notification.
+ *
+ * @returns VBox status.
+ * @param pSrvIns The service instance data.
+ */
+typedef DECLCALLBACK(void) FNPDMSRVRESUME(PPDMSRVINS pSrvIns);
+/** Pointer to a FNPDMSRVRESUME() function. */
+typedef FNPDMSRVRESUME *PFNPDMSRVRESUME;
+
+/**
+ * Power Off notification.
+ *
+ * @param pSrvIns The service instance data.
+ */
+typedef DECLCALLBACK(void) FNPDMSRVPOWEROFF(PPDMSRVINS pSrvIns);
+/** Pointer to a FNPDMSRVPOWEROFF() function. */
+typedef FNPDMSRVPOWEROFF *PFNPDMSRVPOWEROFF;
+
+/**
+ * Detach notification.
+ *
+ * This is called when a driver or device is detached from the service
+ *
+ * @param pSrvIns The service instance data.
+ */
+typedef DECLCALLBACK(void) FNPDMSRVDETACH(PPDMSRVINS pSrvIns, PPDMDEVINS pDevIns, PPDMDRVINS pDrvIns);
+/** Pointer to a FNPDMSRVDETACH() function. */
+typedef FNPDMSRVDETACH *PFNPDMSRVDETACH;
+
+
+
+/** PDM Service Registration Structure,
+ * This structure is used when registering a driver from
+ * VBoxServicesRegister() (HC Ring-3). PDM will continue use till
+ * the VM is terminated.
+ */
+typedef struct PDMSRVREG
+{
+ /** Structure version. PDM_SRVREG_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Driver name. */
+ char szServiceName[32];
+ /** The description of the driver. The UTF-8 string pointed to shall, like this structure,
+ * remain unchanged from registration till VM destruction. */
+ const char *pszDescription;
+
+ /** Flags, combination of the PDM_SRVREG_FLAGS_* \#defines. */
+ RTUINT fFlags;
+ /** Size of the instance data. */
+ RTUINT cbInstance;
+
+ /** Construct instance - required. */
+ PFNPDMSRVCONSTRUCT pfnConstruct;
+ /** Destruct instance - optional. */
+ PFNPDMSRVDESTRUCT pfnDestruct;
+ /** Power on notification - optional. */
+ PFNPDMSRVPOWERON pfnPowerOn;
+ /** Reset notification - optional. */
+ PFNPDMSRVRESET pfnReset;
+ /** Suspend notification - optional. */
+ PFNPDMSRVSUSPEND pfnSuspend;
+ /** Resume notification - optional. */
+ PFNPDMSRVRESUME pfnResume;
+ /** Detach notification - optional. */
+ PFNPDMSRVDETACH pfnDetach;
+ /** Power off notification - optional. */
+ PFNPDMSRVPOWEROFF pfnPowerOff;
+
+} PDMSRVREG;
+/** Pointer to a PDM Driver Structure. */
+typedef PDMSRVREG *PPDMSRVREG;
+/** Const pointer to a PDM Driver Structure. */
+typedef PDMSRVREG const *PCPDMSRVREG;
+
+
+
+/**
+ * PDM Service API.
+ */
+typedef struct PDMSRVHLP
+{
+ /** Structure version. PDM_SRVHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Assert that the current thread is the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pSrvIns Service instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertEMT,(PPDMSRVINS pSrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Assert that the current thread is NOT the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pSrvIns Service instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertOther,(PPDMSRVINS pSrvIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Creates a timer.
+ *
+ * @returns VBox status.
+ * @param pVM The VM to create the timer in.
+ * @param pSrvIns Service instance.
+ * @param enmClock The clock to use on this timer.
+ * @param pfnCallback Callback function.
+ * @param pszDesc Pointer to description string which must stay around
+ * until the timer is fully destroyed (i.e. a bit after TMTimerDestroy()).
+ * @param ppTimer Where to store the timer on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTMTimerCreate,(PPDMSRVINS pSrvIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer));
+
+ /**
+ * Query the virtual timer frequency.
+ *
+ * @returns Frequency in Hz.
+ * @param pSrvIns Service instance.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTMGetVirtualFreq,(PPDMSRVINS pSrvIns));
+
+ /**
+ * Query the virtual time.
+ *
+ * @returns The current virtual time.
+ * @param pSrvIns Service instance.
+ * @thread Any thread.
+ */
+ DECLR3CALLBACKMEMBER(uint64_t, pfnTMGetVirtualTime,(PPDMSRVINS pSrvIns));
+
+} PDMSRVHLP;
+/** Pointer PDM Service API. */
+typedef PDMSRVHLP *PPDMSRVHLP;
+/** Pointer const PDM Service API. */
+typedef const PDMSRVHLP *PCPDMSRVHLP;
+
+/** Current SRVHLP version number. */
+#define PDM_SRVHLP_VERSION PDM_VERSION_MAKE(0xdfff, 1, 0)
+
+
+/**
+ * PDM Service Instance.
+ */
+typedef struct PDMSRVINS
+{
+ /** Structure version. PDM_SRVINS_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /** Internal data. */
+ union
+ {
+#ifdef PDMSRVINSINT_DECLARED
+ PDMSRVINSINT s;
+#endif
+ uint8_t padding[HC_ARCH_BITS == 32 ? 32 : 32];
+ } Internal;
+
+ /** Pointer the PDM Service API. */
+ R3PTRTYPE(PCPDMSRVHLP) pHlp;
+ /** Pointer to driver registration structure. */
+ R3PTRTYPE(PCPDMSRVREG) pReg;
+ /** Configuration handle. */
+ R3PTRTYPE(PCFGMNODE) pCfg;
+ /** The base interface of the service.
+ * The service constructor initializes this. */
+ PDMIBASE IBase;
+ /* padding to make achInstanceData aligned at 16 byte boundary. */
+ uint32_t au32Padding[2];
+ /** Pointer to driver instance data. */
+ R3PTRTYPE(void *) pvInstanceData;
+ /** Driver instance data. The size of this area is defined
+ * in the PDMSRVREG::cbInstanceData field. */
+ char achInstanceData[4];
+} PDMSRVINS;
+
+/** Current PDMSRVREG version number. */
+#define PDM_SRVINS_VERSION PDM_VERSION_MAKE(0xdffe, 1, 0)
+
+/** Converts a pointer to the PDMSRVINS::IBase to a pointer to PDMSRVINS. */
+#define PDMIBASE_2_PDMSRV(pInterface) ( (PPDMSRVINS)((char *)(pInterface) - RT_OFFSETOF(PDMSRVINS, IBase)) )
+
+
+
+/** Pointer to callbacks provided to the VBoxServiceRegister() call. */
+typedef struct PDMSRVREGCB *PPDMSRVREGCB;
+
+/**
+ * Callbacks for VBoxServiceRegister().
+ */
+typedef struct PDMSRVREGCB
+{
+ /** Interface version.
+ * This is set to PDM_SRVREG_CB_VERSION. */
+ uint32_t u32Version;
+
+ /**
+ * Registers a service with the current VM instance.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param pSrvReg Pointer to the device registration record.
+ * This data must be permanent and readonly.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegister,(PPDMSRVREGCB pCallbacks, PCPDMSRVREG pSrvReg));
+} PDMSRVREGCB;
+
+/** Current version of the PDMSRVREGCB structure. */
+#define PDM_SRVREG_CB_VERSION PDM_VERSION_MAKE(0xdffd, 1, 0)
+
+
+/**
+ * The VBoxServicesRegister callback function.
+ *
+ * PDM will invoke this function after loading a device module and letting
+ * the module decide which devices to register and how to handle conflicts.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param u32Version VBox version number.
+ */
+typedef DECLCALLBACK(int) FNPDMVBOXSERVICESREGISTER(PPDMSRVREGCB pCallbacks, uint32_t u32Version);
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
diff --git a/include/VBox/vmm/pdmthread.h b/include/VBox/vmm/pdmthread.h
new file mode 100644
index 00000000..044620cd
--- /dev/null
+++ b/include/VBox/vmm/pdmthread.h
@@ -0,0 +1,298 @@
+/** @file
+ * PDM - Pluggable Device Manager, Threads.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmthread_h
+#define ___VBox_vmm_pdmthread_h
+
+#include <VBox/cdefs.h>
+#include <VBox/types.h>
+#ifdef IN_RING3
+# include <iprt/thread.h>
+#endif
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_thread The PDM Threads API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/**
+ * The thread state
+ */
+typedef enum PDMTHREADSTATE
+{
+ /** The usual invalid 0 entry. */
+ PDMTHREADSTATE_INVALID = 0,
+ /** The thread is initializing.
+ * Prev state: none
+ * Next state: suspended, terminating (error) */
+ PDMTHREADSTATE_INITIALIZING,
+ /** The thread has been asked to suspend.
+ * Prev state: running
+ * Next state: suspended */
+ PDMTHREADSTATE_SUSPENDING,
+ /** The thread is supended.
+ * Prev state: suspending, initializing
+ * Next state: resuming, terminated. */
+ PDMTHREADSTATE_SUSPENDED,
+ /** The thread is active.
+ * Prev state: suspended
+ * Next state: running, terminating. */
+ PDMTHREADSTATE_RESUMING,
+ /** The thread is active.
+ * Prev state: resuming
+ * Next state: suspending, terminating. */
+ PDMTHREADSTATE_RUNNING,
+ /** The thread has been asked to terminate.
+ * Prev state: initializing, suspended, resuming, running
+ * Next state: terminated. */
+ PDMTHREADSTATE_TERMINATING,
+ /** The thread is terminating / has terminated.
+ * Prev state: terminating
+ * Next state: none */
+ PDMTHREADSTATE_TERMINATED,
+ /** The usual 32-bit hack. */
+ PDMTHREADSTATE_32BIT_HACK = 0x7fffffff
+} PDMTHREADSTATE;
+
+/** A pointer to a PDM thread. */
+typedef R3PTRTYPE(struct PDMTHREAD *) PPDMTHREAD;
+/** A pointer to a pointer to a PDM thread. */
+typedef PPDMTHREAD *PPPDMTHREAD;
+
+/**
+ * PDM thread, device variation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pThread The PDM thread data.
+ */
+typedef int FNPDMTHREADDEV(PPDMDEVINS pDevIns, PPDMTHREAD pThread);
+/** Pointer to a FNPDMTHREADDEV(). */
+typedef FNPDMTHREADDEV *PFNPDMTHREADDEV;
+
+/**
+ * PDM thread, USB device variation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param pThread The PDM thread data.
+ */
+typedef int FNPDMTHREADUSB(PPDMUSBINS pUsbIns, PPDMTHREAD pThread);
+/** Pointer to a FNPDMTHREADUSB(). */
+typedef FNPDMTHREADUSB *PFNPDMTHREADUSB;
+
+/**
+ * PDM thread, driver variation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pThread The PDM thread data.
+ */
+typedef int FNPDMTHREADDRV(PPDMDRVINS pDrvIns, PPDMTHREAD pThread);
+/** Pointer to a FNPDMTHREADDRV(). */
+typedef FNPDMTHREADDRV *PFNPDMTHREADDRV;
+
+/**
+ * PDM thread, driver variation.
+ *
+ * @returns VBox status code.
+ * @param pVM The VM handle.
+ * @param pThread The PDM thread data.
+ */
+typedef int FNPDMTHREADINT(PVM pVM, PPDMTHREAD pThread);
+/** Pointer to a FNPDMTHREADINT(). */
+typedef FNPDMTHREADINT *PFNPDMTHREADINT;
+
+/**
+ * PDM thread, driver variation.
+ *
+ * @returns VBox status code.
+ * @param pThread The PDM thread data.
+ */
+typedef int FNPDMTHREADEXT(PPDMTHREAD pThread);
+/** Pointer to a FNPDMTHREADEXT(). */
+typedef FNPDMTHREADEXT *PFNPDMTHREADEXT;
+
+
+
+/**
+ * PDM thread wakeup call, device variation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param pThread The PDM thread data.
+ */
+typedef int FNPDMTHREADWAKEUPDEV(PPDMDEVINS pDevIns, PPDMTHREAD pThread);
+/** Pointer to a FNPDMTHREADDEV(). */
+typedef FNPDMTHREADWAKEUPDEV *PFNPDMTHREADWAKEUPDEV;
+
+/**
+ * PDM thread wakeup call, device variation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param pThread The PDM thread data.
+ */
+typedef int FNPDMTHREADWAKEUPUSB(PPDMUSBINS pUsbIns, PPDMTHREAD pThread);
+/** Pointer to a FNPDMTHREADUSB(). */
+typedef FNPDMTHREADWAKEUPUSB *PFNPDMTHREADWAKEUPUSB;
+
+/**
+ * PDM thread wakeup call, driver variation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns The driver instance.
+ * @param pThread The PDM thread data.
+ */
+typedef int FNPDMTHREADWAKEUPDRV(PPDMDRVINS pDrvIns, PPDMTHREAD pThread);
+/** Pointer to a FNPDMTHREADDRV(). */
+typedef FNPDMTHREADWAKEUPDRV *PFNPDMTHREADWAKEUPDRV;
+
+/**
+ * PDM thread wakeup call, internal variation.
+ *
+ * @returns VBox status code.
+ * @param pVM The VM handle.
+ * @param pThread The PDM thread data.
+ */
+typedef int FNPDMTHREADWAKEUPINT(PVM pVM, PPDMTHREAD pThread);
+/** Pointer to a FNPDMTHREADWAKEUPINT(). */
+typedef FNPDMTHREADWAKEUPINT *PFNPDMTHREADWAKEUPINT;
+
+/**
+ * PDM thread wakeup call, external variation.
+ *
+ * @returns VBox status code.
+ * @param pThread The PDM thread data.
+ */
+typedef int FNPDMTHREADWAKEUPEXT(PPDMTHREAD pThread);
+/** Pointer to a FNPDMTHREADEXT(). */
+typedef FNPDMTHREADWAKEUPEXT *PFNPDMTHREADWAKEUPEXT;
+
+
+/**
+ * PDM Thread instance data.
+ */
+typedef struct PDMTHREAD
+{
+ /** PDMTHREAD_VERSION. */
+ uint32_t u32Version;
+ /** The thread state. */
+ PDMTHREADSTATE volatile enmState;
+ /** The thread handle. */
+ RTTHREAD Thread;
+ /** The user parameter. */
+ R3PTRTYPE(void *) pvUser;
+ /** Data specific to the kind of thread.
+ * This should really be in PDMTHREADINT, but is placed here because of the
+ * function pointer typedefs. So, don't touch these, please.
+ */
+ union
+ {
+ /** PDMTHREADTYPE_DEVICE data. */
+ struct
+ {
+ /** The device instance. */
+ PPDMDEVINSR3 pDevIns;
+ /** The thread function. */
+ R3PTRTYPE(PFNPDMTHREADDEV) pfnThread;
+ /** Thread. */
+ R3PTRTYPE(PFNPDMTHREADWAKEUPDEV) pfnWakeUp;
+ } Dev;
+
+ /** PDMTHREADTYPE_USB data. */
+ struct
+ {
+ /** The device instance. */
+ PPDMUSBINS pUsbIns;
+ /** The thread function. */
+ R3PTRTYPE(PFNPDMTHREADUSB) pfnThread;
+ /** Thread. */
+ R3PTRTYPE(PFNPDMTHREADWAKEUPUSB) pfnWakeUp;
+ } Usb;
+
+ /** PDMTHREADTYPE_DRIVER data. */
+ struct
+ {
+ /** The driver instance. */
+ R3PTRTYPE(PPDMDRVINS) pDrvIns;
+ /** The thread function. */
+ R3PTRTYPE(PFNPDMTHREADDRV) pfnThread;
+ /** Thread. */
+ R3PTRTYPE(PFNPDMTHREADWAKEUPDRV) pfnWakeUp;
+ } Drv;
+
+ /** PDMTHREADTYPE_INTERNAL data. */
+ struct
+ {
+ /** The thread function. */
+ R3PTRTYPE(PFNPDMTHREADINT) pfnThread;
+ /** Thread. */
+ R3PTRTYPE(PFNPDMTHREADWAKEUPINT) pfnWakeUp;
+ } Int;
+
+ /** PDMTHREADTYPE_EXTERNAL data. */
+ struct
+ {
+ /** The thread function. */
+ R3PTRTYPE(PFNPDMTHREADEXT) pfnThread;
+ /** Thread. */
+ R3PTRTYPE(PFNPDMTHREADWAKEUPEXT) pfnWakeUp;
+ } Ext;
+ } u;
+
+ /** Internal data. */
+ union
+ {
+#ifdef PDMTHREADINT_DECLARED
+ PDMTHREADINT s;
+#endif
+ uint8_t padding[64];
+ } Internal;
+} PDMTHREAD;
+
+/** PDMTHREAD::u32Version value. */
+#define PDMTHREAD_VERSION PDM_VERSION_MAKE(0xefff, 1, 0)
+
+#ifdef IN_RING3
+VMMR3DECL(int) PDMR3ThreadCreate(PVM pVM, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADINT pfnThread,
+ PFNPDMTHREADWAKEUPINT pfnWakeUp, size_t cbStack, RTTHREADTYPE enmType, const char *pszName);
+VMMR3DECL(int) PDMR3ThreadCreateExternal(PVM pVM, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADEXT pfnThread,
+ PFNPDMTHREADWAKEUPEXT pfnWakeUp, size_t cbStack, RTTHREADTYPE enmType, const char *pszName);
+VMMR3DECL(int) PDMR3ThreadDestroy(PPDMTHREAD pThread, int *pRcThread);
+VMMR3DECL(int) PDMR3ThreadIAmSuspending(PPDMTHREAD pThread);
+VMMR3DECL(int) PDMR3ThreadIAmRunning(PPDMTHREAD pThread);
+VMMR3DECL(int) PDMR3ThreadSleep(PPDMTHREAD pThread, RTMSINTERVAL cMillies);
+VMMR3DECL(int) PDMR3ThreadSuspend(PPDMTHREAD pThread);
+VMMR3DECL(int) PDMR3ThreadResume(PPDMTHREAD pThread);
+#endif /* IN_RING3 */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
diff --git a/include/VBox/vmm/pdmusb.h b/include/VBox/vmm/pdmusb.h
new file mode 100644
index 00000000..ae3f5cfb
--- /dev/null
+++ b/include/VBox/vmm/pdmusb.h
@@ -0,0 +1,1004 @@
+/** @file
+ * PDM - Pluggable Device Manager, USB Devices.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pdmusb_h
+#define ___VBox_vmm_pdmusb_h
+
+#include <VBox/vmm/pdmqueue.h>
+#include <VBox/vmm/pdmcritsect.h>
+#include <VBox/vmm/pdmthread.h>
+#include <VBox/vmm/pdmifs.h>
+#include <VBox/vmm/pdmcommon.h>
+#include <VBox/vmm/tm.h>
+#include <VBox/vmm/ssm.h>
+#include <VBox/vmm/cfgm.h>
+#include <VBox/vmm/dbgf.h>
+#include <VBox/vmm/mm.h>
+#include <VBox/err.h>
+#include <VBox/vusb.h>
+#include <iprt/stdarg.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pdm_usbdev The USB Devices API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+
+/**
+ * A string entry for the USB descriptor cache.
+ */
+typedef struct PDMUSBDESCCACHESTRING
+{
+ /** The string index. */
+ uint8_t idx;
+ /** The UTF-8 representation of the string. */
+ const char *psz;
+} PDMUSBDESCCACHESTRING;
+/** Pointer to a const string entry. */
+typedef PDMUSBDESCCACHESTRING const *PCPDMUSBDESCCACHESTRING;
+
+
+/**
+ * A language entry for the USB descriptor cache.
+ */
+typedef struct PDMUSBDESCCACHELANG
+{
+ /** The language ID for the strings in this block. */
+ uint16_t idLang;
+ /** The number of strings in the array. */
+ uint16_t cStrings;
+ /** Pointer to an array of associated strings.
+ * This must be sorted in ascending order by string index as a binary lookup
+ * will be performed. */
+ PCPDMUSBDESCCACHESTRING paStrings;
+} PDMUSBDESCCACHELANG;
+/** Pointer to a const language entry. */
+typedef PDMUSBDESCCACHELANG const *PCPDMUSBDESCCACHELANG;
+
+
+/**
+ * USB descriptor cache.
+ *
+ * This structure is owned by the USB device but provided to the PDM/VUSB layer
+ * thru the PDMUSBREG::pfnGetDescriptorCache method. PDM/VUSB will use the
+ * information here to map addresses to endpoints, perform SET_CONFIGURATION
+ * requests, and optionally perform GET_DESCRIPTOR requests (see flag).
+ *
+ * Currently, only device and configuration descriptors are cached.
+ */
+typedef struct PDMUSBDESCCACHE
+{
+ /** USB device descriptor */
+ PCVUSBDESCDEVICE pDevice;
+ /** USB Descriptor arrays (pDev->bNumConfigurations) */
+ PCVUSBDESCCONFIGEX paConfigs;
+ /** Language IDs and their associated strings.
+ * This must be sorted in ascending order by language ID as a binary lookup
+ * will be used. */
+ PCPDMUSBDESCCACHELANG paLanguages;
+ /** The number of entries in the array pointed to by paLanguages. */
+ uint16_t cLanguages;
+ /** Use the cached descriptors for GET_DESCRIPTOR requests. */
+ bool fUseCachedDescriptors;
+ /** Use the cached string descriptors. */
+ bool fUseCachedStringsDescriptors;
+} PDMUSBDESCCACHE;
+/** Pointer to an USB descriptor cache. */
+typedef PDMUSBDESCCACHE *PPDMUSBDESCCACHE;
+/** Pointer to a const USB descriptor cache. */
+typedef const PDMUSBDESCCACHE *PCPDMUSBDESCCACHE;
+
+
+
+/** PDM USB Device Registration Structure,
+ *
+ * This structure is used when registering a device from VBoxUsbRegister() in HC Ring-3.
+ * The PDM will make use of this structure until the VM is destroyed.
+ */
+typedef struct PDMUSBREG
+{
+ /** Structure version. PDM_DEVREG_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** Device name. */
+ char szName[32];
+ /** The description of the device. The UTF-8 string pointed to shall, like this structure,
+ * remain unchanged from registration till VM destruction. */
+ const char *pszDescription;
+
+ /** Flags, combination of the PDM_USBREG_FLAGS_* \#defines. */
+ RTUINT fFlags;
+ /** Maximum number of instances (per VM). */
+ RTUINT cMaxInstances;
+ /** Size of the instance data. */
+ RTUINT cbInstance;
+
+
+ /**
+ * Construct an USB device instance for a VM.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance data.
+ * If the registration structure is needed, it will be
+ * accessible thru pUsbDev->pReg.
+ * @param iInstance Instance number. Use this to figure out which registers
+ * and such to use. The instance number is also found in
+ * pUsbDev->iInstance, but since it's likely to be
+ * frequently used PDM passes it as parameter.
+ * @param pCfg Configuration node handle for the device. Use this to
+ * obtain the configuration of the device instance. It is
+ * also found in pUsbDev->pCfg, but since it is primary
+ * usage will in this function it is passed as a parameter.
+ * @param pCfgGlobal Handle to the global device configuration. Also found
+ * in pUsbDev->pCfgGlobal.
+ * @remarks This callback is required.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnConstruct,(PPDMUSBINS pUsbIns, int iInstance, PCFGMNODE pCfg, PCFGMNODE pCfgGlobal));
+
+ /**
+ * Destruct an USB device instance.
+ *
+ * Most VM resources are freed by the VM. This callback is provided so that any non-VM
+ * resources can be freed correctly.
+ *
+ * This method will be called regardless of the pfnConstruc result to avoid
+ * complicated failure paths.
+ *
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnDestruct,(PPDMUSBINS pUsbIns));
+
+
+ /**
+ * Init complete notification.
+ *
+ * This can be done to do communication with other devices and other
+ * initialization which requires everything to be in place.
+ *
+ * @returns VBOX status code.
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ * @remarks Not called when hotplugged.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMInitComplete,(PPDMUSBINS pUsbIns));
+
+ /**
+ * VM Power On notification.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVMPowerOn,(PPDMUSBINS pUsbIns));
+
+ /**
+ * VM Reset notification.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVMReset,(PPDMUSBINS pUsbIns));
+
+ /**
+ * VM Suspend notification.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVMSuspend,(PPDMUSBINS pUsbIns));
+
+ /**
+ * VM Resume notification.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVMResume,(PPDMUSBINS pUsbIns));
+
+ /**
+ * VM Power Off notification.
+ *
+ * This is only called when the VMR3PowerOff call is made on a running VM. This
+ * means that there is no notification if the VM was suspended before being
+ * powered of. There will also be no callback when hot plugging devices.
+ *
+ * @param pUsbIns The USB device instance data.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnVMPowerOff,(PPDMUSBINS pUsbIns));
+
+ /**
+ * Called after the constructor when attaching a device at run time.
+ *
+ * This can be used to do tasks normally assigned to pfnInitComplete and/or pfnVMPowerOn.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnHotPlugged,(PPDMUSBINS pUsbIns));
+
+ /**
+ * Called before the destructor when a device is unplugged at run time.
+ *
+ * This can be used to do tasks normally assigned to pfnVMSuspend and/or pfnVMPowerOff.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance data.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnHotUnplugged,(PPDMUSBINS pUsbIns));
+ /**
+ * Driver Attach command.
+ *
+ * This is called to let the USB device attach to a driver for a specified LUN
+ * at runtime. This is not called during VM construction, the device constructor
+ * have to attach to all the available drivers.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance data.
+ * @param iLUN The logical unit which is being detached.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDriverAttach,(PPDMUSBINS pUsbIns, unsigned iLUN));
+
+ /**
+ * Driver Detach notification.
+ *
+ * This is called when a driver is detaching itself from a LUN of the device.
+ * The device should adjust it's state to reflect this.
+ *
+ * @param pUsbIns The USB device instance data.
+ * @param iLUN The logical unit which is being detached.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnDriverDetach,(PPDMUSBINS pUsbIns, unsigned iLUN));
+
+ /**
+ * Query the base interface of a logical unit.
+ *
+ * @returns VBOX status code.
+ * @param pUsbIns The USB device instance data.
+ * @param iLUN The logicial unit to query.
+ * @param ppBase Where to store the pointer to the base interface of the LUN.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnQueryInterface,(PPDMUSBINS pUsbIns, unsigned iLUN, PPDMIBASE *ppBase));
+
+ /**
+ * Requests the USB device to reset.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param fResetOnLinux A hint to the usb proxy.
+ * Don't use this unless you're the linux proxy device.
+ * @thread Any thread.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUsbReset,(PPDMUSBINS pUsbIns, bool fResetOnLinux));
+
+ /**
+ * Query device and configuration descriptors for the caching and servicing
+ * relevant GET_DESCRIPTOR requests.
+ *
+ * @returns Pointer to the descriptor cache (read-only).
+ * @param pUsbIns The USB device instance.
+ * @remarks Mandatory.
+ */
+ DECLR3CALLBACKMEMBER(PCPDMUSBDESCCACHE, pfnUsbGetDescriptorCache,(PPDMUSBINS pUsbIns));
+
+ /**
+ * SET_CONFIGURATION request.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param bConfigurationValue The bConfigurationValue of the new configuration.
+ * @param pvOldCfgDesc Internal - for the device proxy.
+ * @param pvOldIfState Internal - for the device proxy.
+ * @param pvNewCfgDesc Internal - for the device proxy.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUsbSetConfiguration,(PPDMUSBINS pUsbIns, uint8_t bConfigurationValue,
+ const void *pvOldCfgDesc, const void *pvOldIfState, const void *pvNewCfgDesc));
+
+ /**
+ * SET_INTERFACE request.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param bInterfaceNumber The interface number.
+ * @param bAlternateSetting The alternate setting.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUsbSetInterface,(PPDMUSBINS pUsbIns, uint8_t bInterfaceNumber, uint8_t bAlternateSetting));
+
+ /**
+ * Clears the halted state of an endpoint. (Optional)
+ *
+ * This called when VUSB sees a CLEAR_FEATURE(ENDPOINT_HALT) on request
+ * on the zero pipe.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param uEndpoint The endpoint to clear.
+ * @remarks Optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUsbClearHaltedEndpoint,(PPDMUSBINS pUsbIns, unsigned uEndpoint));
+
+ /**
+ * Allocates an URB.
+ *
+ * This can be used to make use of shared user/kernel mode buffers.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param cbData The size of the data buffer.
+ * @param cTds The number of TDs.
+ * @param enmType The type of URB.
+ * @param ppUrb Where to store the allocated URB.
+ * @remarks Optional.
+ * @remarks Not implemented yet.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUrbNew,(PPDMUSBINS pUsbIns, size_t cbData, size_t cTds, VUSBXFERTYPE enmType, PVUSBURB *ppUrb));
+
+ /**
+ * Queues an URB for processing.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS on success.
+ * @retval VERR_VUSB_DEVICE_NOT_ATTACHED if the device has been disconnected.
+ * @retval VERR_VUSB_FAILED_TO_QUEUE_URB as a general failure kind of thing.
+ * @retval TBD - document new stuff!
+ *
+ * @param pUsbIns The USB device instance.
+ * @param pUrb The URB to process.
+ * @remarks Mandatory.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUrbQueue,(PPDMUSBINS pUsbIns, PVUSBURB pUrb));
+
+ /**
+ * Cancels an URB.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param pUrb The URB to cancel.
+ * @remarks Mandatory.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnUrbCancel,(PPDMUSBINS pUsbIns, PVUSBURB pUrb));
+
+ /**
+ * Reaps an URB.
+ *
+ * @returns A ripe URB, NULL if none.
+ * @param pUsbIns The USB device instance.
+ * @param cMillies How log to wait for an URB to become ripe.
+ * @remarks Mandatory.
+ */
+ DECLR3CALLBACKMEMBER(PVUSBURB, pfnUrbReap,(PPDMUSBINS pUsbIns, RTMSINTERVAL cMillies));
+
+
+ /** Just some init precaution. Must be set to PDM_USBREG_VERSION. */
+ uint32_t u32TheEnd;
+} PDMUSBREG;
+/** Pointer to a PDM USB Device Structure. */
+typedef PDMUSBREG *PPDMUSBREG;
+/** Const pointer to a PDM USB Device Structure. */
+typedef PDMUSBREG const *PCPDMUSBREG;
+
+/** Current USBREG version number. */
+#define PDM_USBREG_VERSION PDM_VERSION_MAKE(0xeeff, 1, 0)
+
+/** PDM USB Device Flags.
+ * @{ */
+/* none yet */
+/** @} */
+
+
+#ifdef IN_RING3
+
+/**
+ * PDM USB Device API.
+ */
+typedef struct PDMUSBHLP
+{
+ /** Structure version. PDM_USBHLP_VERSION defines the current version. */
+ uint32_t u32Version;
+
+ /**
+ * Attaches a driver (chain) to the USB device.
+ *
+ * The first call for a LUN this will serve as a registartion of the LUN. The pBaseInterface and
+ * the pszDesc string will be registered with that LUN and kept around for PDMR3QueryUSBDeviceLun().
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param iLun The logical unit to attach.
+ * @param pBaseInterface Pointer to the base interface for that LUN. (device side / down)
+ * @param ppBaseInterface Where to store the pointer to the base interface. (driver side / up)
+ * @param pszDesc Pointer to a string describing the LUN. This string must remain valid
+ * for the live of the device instance.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDriverAttach,(PPDMUSBINS pUsbIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc));
+
+ /**
+ * Assert that the current thread is the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pUsbIns The USB device instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertEMT,(PPDMUSBINS pUsbIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Assert that the current thread is NOT the emulation thread.
+ *
+ * @returns True if correct.
+ * @returns False if wrong.
+ * @param pUsbIns The USB device instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine Linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ */
+ DECLR3CALLBACKMEMBER(bool, pfnAssertOther,(PPDMUSBINS pUsbIns, const char *pszFile, unsigned iLine, const char *pszFunction));
+
+ /**
+ * Stops the VM and enters the debugger to look at the guest state.
+ *
+ * Use the PDMUsbDBGFStop() inline function with the RT_SRC_POS macro instead of
+ * invoking this function directly.
+ *
+ * @returns VBox status code which must be passed up to the VMM.
+ * @param pUsbIns The USB device instance.
+ * @param pszFile Filename of the assertion location.
+ * @param iLine The linenumber of the assertion location.
+ * @param pszFunction Function of the assertion location.
+ * @param pszFormat Message. (optional)
+ * @param va Message parameters.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFStopV,(PPDMUSBINS pUsbIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list va));
+
+ /**
+ * Register a info handler with DBGF,
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param pszName The identifier of the info.
+ * @param pszDesc The description of the info and any arguments the handler may take.
+ * @param pfnHandler The handler function to be called to display the info.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnDBGFInfoRegister,(PPDMUSBINS pUsbIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERUSB pfnHandler));
+
+ /**
+ * Allocate memory which is associated with current VM instance
+ * and automatically freed on it's destruction.
+ *
+ * @returns Pointer to allocated memory. The memory is *NOT* zero-ed.
+ * @param pUsbIns The USB device instance.
+ * @param cb Number of bytes to allocate.
+ */
+ DECLR3CALLBACKMEMBER(void *, pfnMMHeapAlloc,(PPDMUSBINS pUsbIns, size_t cb));
+
+ /**
+ * Allocate memory which is associated with current VM instance
+ * and automatically freed on it's destruction. The memory is ZEROed.
+ *
+ * @returns Pointer to allocated memory. The memory is *NOT* zero-ed.
+ * @param pUsbIns The USB device instance.
+ * @param cb Number of bytes to allocate.
+ */
+ DECLR3CALLBACKMEMBER(void *, pfnMMHeapAllocZ,(PPDMUSBINS pUsbIns, size_t cb));
+
+ /**
+ * Create a queue.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param cbItem Size a queue item.
+ * @param cItems Number of items in the queue.
+ * @param cMilliesInterval Number of milliseconds between polling the queue.
+ * If 0 then the emulation thread will be notified whenever an item arrives.
+ * @param pfnCallback The consumer function.
+ * @param pszName The queue base name. The instance number will be
+ * appended automatically.
+ * @param ppQueue Where to store the queue handle on success.
+ * @thread The emulation thread.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnPDMQueueCreate,(PPDMUSBINS pUsbIns, RTUINT cbItem, RTUINT cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEUSB pfnCallback, const char *pszName, PPDMQUEUE *ppQueue));
+
+ /**
+ * Register a save state data unit.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance.
+ * @param uVersion Data layout version number.
+ * @param cbGuess The approximate amount of data in the unit.
+ * Only for progress indicators.
+ *
+ * @param pfnLivePrep Prepare live save callback, optional.
+ * @param pfnLiveExec Execute live save callback, optional.
+ * @param pfnLiveVote Vote live save callback, optional.
+ *
+ * @param pfnSavePrep Prepare save callback, optional.
+ * @param pfnSaveExec Execute save callback, optional.
+ * @param pfnSaveDone Done save callback, optional.
+ *
+ * @param pfnLoadPrep Prepare load callback, optional.
+ * @param pfnLoadExec Execute load callback, optional.
+ * @param pfnLoadDone Done load callback, optional.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSSMRegister,(PPDMUSBINS pUsbIns, uint32_t uVersion, size_t cbGuess,
+ PFNSSMUSBLIVEPREP pfnLivePrep, PFNSSMUSBLIVEEXEC pfnLiveExec, PFNSSMUSBLIVEVOTE pfnLiveVote,
+ PFNSSMUSBSAVEPREP pfnSavePrep, PFNSSMUSBSAVEEXEC pfnSaveExec, PFNSSMUSBSAVEDONE pfnSaveDone,
+ PFNSSMUSBLOADPREP pfnLoadPrep, PFNSSMUSBLOADEXEC pfnLoadExec, PFNSSMUSBLOADDONE pfnLoadDone));
+
+ /**
+ * Register a STAM sample.
+ *
+ * Use the PDMUsbHlpSTAMRegister wrapper.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param enmVisibility Visibility type specifying whether unused statistics should be visible or not.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ * @param pszName The sample name format string.
+ * @param va Arguments to the format string.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnSTAMRegisterV,(PPDMUSBINS pUsbIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list va));
+
+ /**
+ * Creates a timer.
+ *
+ * @returns VBox status.
+ * @param pUsbIns The USB device instance.
+ * @param enmClock The clock to use on this timer.
+ * @param pfnCallback Callback function.
+ * @param pvUser User argument for the callback.
+ * @param fFlags Flags, see TMTIMER_FLAGS_*.
+ * @param pszDesc Pointer to description string which must stay around
+ * until the timer is fully destroyed (i.e. a bit after TMTimerDestroy()).
+ * @param ppTimer Where to store the timer on success.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTMTimerCreate,(PPDMUSBINS pUsbIns, TMCLOCK enmClock, PFNTMTIMERUSB pfnCallback, void *pvUser,
+ uint32_t fFlags, const char *pszDesc, PPTMTIMERR3 ppTimer));
+
+ /**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pUsbIns The USB device instance.
+ * @param rc VBox status code.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetErrorV,(PPDMUSBINS pUsbIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va));
+
+ /**
+ * Set the VM runtime error message
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance.
+ * @param fFlags The action flags. See VMSETRTERR_FLAGS_*.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnVMSetRuntimeErrorV,(PPDMUSBINS pUsbIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va));
+
+ /**
+ * Gets the VM state.
+ *
+ * @returns VM state.
+ * @param pUsbIns The USB device instance.
+ * @thread Any thread (just keep in mind that it's volatile info).
+ */
+ DECLR3CALLBACKMEMBER(VMSTATE, pfnVMState, (PPDMUSBINS pUsbIns));
+
+ /**
+ * Creates a PDM thread.
+ *
+ * This differs from the RTThreadCreate() API in that PDM takes care of suspending,
+ * resuming, and destroying the thread as the VM state changes.
+ *
+ * @returns VBox status code.
+ * @param pDevIns The device instance.
+ * @param ppThread Where to store the thread 'handle'.
+ * @param pvUser The user argument to the thread function.
+ * @param pfnThread The thread function.
+ * @param pfnWakeup The wakup callback. This is called on the EMT
+ * thread when a state change is pending.
+ * @param cbStack See RTThreadCreate.
+ * @param enmType See RTThreadCreate.
+ * @param pszName See RTThreadCreate.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnThreadCreate,(PPDMUSBINS pUsbIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADUSB pfnThread,
+ PFNPDMTHREADWAKEUPUSB pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName));
+
+ /**
+ * Set up asynchronous handling of a suspend, reset or power off notification.
+ *
+ * This shall only be called when getting the notification. It must be called
+ * for each one.
+ *
+ * @returns VBox status code.
+ * @param pUSBIns The USB device instance.
+ * @param pfnAsyncNotify The callback.
+ * @thread EMT(0)
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSetAsyncNotification, (PPDMUSBINS pUSbIns, PFNPDMUSBASYNCNOTIFY pfnAsyncNotify));
+
+ /**
+ * Notify EMT(0) that the device has completed the asynchronous notification
+ * handling.
+ *
+ * This can be called at any time, spurious calls will simply be ignored.
+ *
+ * @param pUSBIns The USB device instance.
+ * @thread Any
+ */
+ DECLR3CALLBACKMEMBER(void, pfnAsyncNotificationCompleted, (PPDMUSBINS pUsbIns));
+
+ /** Just a safety precaution. */
+ uint32_t u32TheEnd;
+} PDMUSBHLP;
+/** Pointer PDM USB Device API. */
+typedef PDMUSBHLP *PPDMUSBHLP;
+/** Pointer const PDM USB Device API. */
+typedef const PDMUSBHLP *PCPDMUSBHLP;
+
+/** Current USBHLP version number. */
+#define PDM_USBHLP_VERSION PDM_VERSION_MAKE(0xeefe, 2, 0)
+
+#endif /* IN_RING3 */
+
+/**
+ * PDM USB Device Instance.
+ */
+typedef struct PDMUSBINS
+{
+ /** Structure version. PDM_USBINS_VERSION defines the current version. */
+ uint32_t u32Version;
+ /** USB device instance number. */
+ uint32_t iInstance;
+ /** The base interface of the device.
+ * The device constructor initializes this if it has any device level
+ * interfaces to export. To obtain this interface call PDMR3QueryUSBDevice(). */
+ PDMIBASE IBase;
+#if HC_ARCH_BITS == 32
+ uint32_t u32Alignment; /**< Alignment padding. */
+#endif
+
+ /** Internal data. */
+ union
+ {
+#ifdef PDMUSBINSINT_DECLARED
+ PDMUSBINSINT s;
+#endif
+ uint8_t padding[HC_ARCH_BITS == 32 ? 96 : 128];
+ } Internal;
+
+ /** Pointer the PDM USB Device API. */
+ R3PTRTYPE(PCPDMUSBHLP) pHlpR3;
+ /** Pointer to the USB device registration structure. */
+ R3PTRTYPE(PCPDMUSBREG) pReg;
+ /** Configuration handle. */
+ R3PTRTYPE(PCFGMNODE) pCfg;
+ /** The (device) global configuration handle. */
+ R3PTRTYPE(PCFGMNODE) pCfgGlobal;
+ /** Pointer to device instance data. */
+ R3PTRTYPE(void *) pvInstanceDataR3;
+ /** Pointer to the VUSB Device structure.
+ * Internal to VUSB, don't touch.
+ * @todo Moved this to PDMUSBINSINT. */
+ R3PTRTYPE(void *) pvVUsbDev2;
+ /** Device name for using when logging.
+ * The constructor sets this and the destructor frees it. */
+ R3PTRTYPE(char *) pszName;
+ /** Tracing indicator. */
+ uint32_t fTracing;
+ /** The tracing ID of this device. */
+ uint32_t idTracing;
+
+ /** Padding to make achInstanceData aligned at 32 byte boundary. */
+ uint32_t au32Padding[HC_ARCH_BITS == 32 ? 3 : 4];
+
+ /** Device instance data. The size of this area is defined
+ * in the PDMUSBREG::cbInstanceData field. */
+ char achInstanceData[8];
+} PDMUSBINS;
+
+/** Current USBINS version number. */
+#define PDM_USBINS_VERSION PDM_VERSION_MAKE(0xeefd, 2, 0)
+
+/**
+ * Checks the structure versions of the USB device instance and USB device
+ * helpers, returning if they are incompatible.
+ *
+ * This is for use in the constructor.
+ *
+ * @param pUsbIns The USB device instance pointer.
+ */
+#define PDMUSB_CHECK_VERSIONS_RETURN(pUsbIns) \
+ do \
+ { \
+ PPDMUSBINS pUsbInsTypeCheck = (pUsbIns); NOREF(pUsbInsTypeCheck); \
+ AssertLogRelMsgReturn(PDM_VERSION_ARE_COMPATIBLE((pUsbIns)->u32Version, PDM_USBINS_VERSION), \
+ ("DevIns=%#x mine=%#x\n", (pUsbIns)->u32Version, PDM_USBINS_VERSION), \
+ VERR_PDM_USBINS_VERSION_MISMATCH); \
+ AssertLogRelMsgReturn(PDM_VERSION_ARE_COMPATIBLE((pUsbIns)->pHlpR3->u32Version, PDM_USBHLP_VERSION), \
+ ("DevHlp=%#x mine=%#x\n", (pUsbIns)->pHlpR3->u32Version, PDM_USBHLP_VERSION), \
+ VERR_PDM_USBHLPR3_VERSION_MISMATCH); \
+ } while (0)
+
+/**
+ * Quietly checks the structure versions of the USB device instance and
+ * USB device helpers, returning if they are incompatible.
+ *
+ * This is for use in the destructor.
+ *
+ * @param pUsbIns The USB device instance pointer.
+ */
+#define PDMUSB_CHECK_VERSIONS_RETURN_QUIET(pUsbIns) \
+ do \
+ { \
+ PPDMUSBINS pUsbInsTypeCheck = (pUsbIns); NOREF(pUsbInsTypeCheck); \
+ if (RT_UNLIKELY(!PDM_VERSION_ARE_COMPATIBLE((pUsbIns)->u32Version, PDM_USBINS_VERSION) )) \
+ return VERR_PDM_USBINS_VERSION_MISMATCH; \
+ if (RT_UNLIKELY(!PDM_VERSION_ARE_COMPATIBLE((pUsbIns)->pHlpR3->u32Version, PDM_USBHLPR3_VERSION) )) \
+ return VERR_PDM_USBHLPR3_VERSION_MISMATCH; \
+ } while (0)
+
+
+/** Converts a pointer to the PDMUSBINS::IBase to a pointer to PDMUSBINS. */
+#define PDMIBASE_2_PDMUSB(pInterface) ( (PPDMUSBINS)((char *)(pInterface) - RT_OFFSETOF(PDMUSBINS, IBase)) )
+
+
+/** @def PDMUSB_ASSERT_EMT
+ * Assert that the current thread is the emulation thread.
+ */
+#ifdef VBOX_STRICT
+# define PDMUSB_ASSERT_EMT(pUsbIns) pUsbIns->pHlpR3->pfnAssertEMT(pUsbIns, __FILE__, __LINE__, __FUNCTION__)
+#else
+# define PDMUSB_ASSERT_EMT(pUsbIns) do { } while (0)
+#endif
+
+/** @def PDMUSB_ASSERT_OTHER
+ * Assert that the current thread is NOT the emulation thread.
+ */
+#ifdef VBOX_STRICT
+# define PDMUSB_ASSERT_OTHER(pUsbIns) pUsbIns->pHlpR3->pfnAssertOther(pUsbIns, __FILE__, __LINE__, __FUNCTION__)
+#else
+# define PDMUSB_ASSERT_OTHER(pUsbIns) do { } while (0)
+#endif
+
+/** @def PDMUSB_SET_ERROR
+ * Set the VM error. See PDMUsbHlpVMSetError() for printf like message
+ * formatting.
+ */
+#define PDMUSB_SET_ERROR(pUsbIns, rc, pszError) \
+ PDMUsbHlpVMSetError(pUsbIns, rc, RT_SRC_POS, "%s", pszError)
+
+/** @def PDMUSB_SET_RUNTIME_ERROR
+ * Set the VM runtime error. See PDMUsbHlpVMSetRuntimeError() for printf like
+ * message formatting.
+ */
+#define PDMUSB_SET_RUNTIME_ERROR(pUsbIns, fFlags, pszErrorId, pszError) \
+ PDMUsbHlpVMSetRuntimeError(pUsbIns, fFlags, pszErrorId, "%s", pszError)
+
+
+#ifdef IN_RING3
+
+/**
+ * @copydoc PDMUSBHLP::pfnDriverAttach
+ */
+DECLINLINE(int) PDMUsbHlpDriverAttach(PPDMUSBINS pUsbIns, RTUINT iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
+{
+ return pUsbIns->pHlpR3->pfnDriverAttach(pUsbIns, iLun, pBaseInterface, ppBaseInterface, pszDesc);
+}
+
+/**
+ * VBOX_STRICT wrapper for pHlpR3->pfnDBGFStopV.
+ *
+ * @returns VBox status code which must be passed up to the VMM.
+ * @param pUsbIns Device instance.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Message. (optional)
+ * @param ... Message parameters.
+ */
+DECLINLINE(int) PDMUsbDBGFStop(PPDMUSBINS pUsbIns, RT_SRC_POS_DECL, const char *pszFormat, ...)
+{
+#ifdef VBOX_STRICT
+ int rc;
+ va_list va;
+ va_start(va, pszFormat);
+ rc = pUsbIns->pHlpR3->pfnDBGFStopV(pUsbIns, RT_SRC_POS_ARGS, pszFormat, va);
+ va_end(va);
+ return rc;
+#else
+ NOREF(pUsbIns);
+ NOREF(pszFile);
+ NOREF(iLine);
+ NOREF(pszFunction);
+ NOREF(pszFormat);
+ return VINF_SUCCESS;
+#endif
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnVMState
+ */
+DECLINLINE(VMSTATE) PDMUsbHlpVMState(PPDMUSBINS pUsbIns)
+{
+ return pUsbIns->pHlpR3->pfnVMState(pUsbIns);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnThreadCreate
+ */
+DECLINLINE(int) PDMUsbHlpThreadCreate(PPDMUSBINS pUsbIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADUSB pfnThread,
+ PFNPDMTHREADWAKEUPUSB pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
+{
+ return pUsbIns->pHlpR3->pfnThreadCreate(pUsbIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
+}
+
+
+/**
+ * @copydoc PDMUSBHLP::pfnSetAsyncNotification
+ */
+DECLINLINE(int) PDMUsbHlpSetAsyncNotification(PPDMUSBINS pUsbIns, PFNPDMUSBASYNCNOTIFY pfnAsyncNotify)
+{
+ return pUsbIns->pHlpR3->pfnSetAsyncNotification(pUsbIns, pfnAsyncNotify);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnAsyncNotificationCompleted
+ */
+DECLINLINE(void) PDMUsbHlpAsyncNotificationCompleted(PPDMUSBINS pUsbIns)
+{
+ pUsbIns->pHlpR3->pfnAsyncNotificationCompleted(pUsbIns);
+}
+
+/**
+ * Set the VM error message
+ *
+ * @returns rc.
+ * @param pUsbIns The USB device instance.
+ * @param rc VBox status code.
+ * @param RT_SRC_POS_DECL Use RT_SRC_POS.
+ * @param pszFormat Error message format string.
+ * @param ... Error message arguments.
+ */
+DECLINLINE(int) PDMUsbHlpVMSetError(PPDMUSBINS pUsbIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
+{
+ va_list va;
+ va_start(va, pszFormat);
+ rc = pUsbIns->pHlpR3->pfnVMSetErrorV(pUsbIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
+ va_end(va);
+ return rc;
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnMMHeapAlloc
+ */
+DECLINLINE(void *) PDMUsbHlpMMHeapAlloc(PPDMUSBINS pUsbIns, size_t cb)
+{
+ return pUsbIns->pHlpR3->pfnMMHeapAlloc(pUsbIns, cb);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnMMHeapAllocZ
+ */
+DECLINLINE(void *) PDMUsbHlpMMHeapAllocZ(PPDMUSBINS pUsbIns, size_t cb)
+{
+ return pUsbIns->pHlpR3->pfnMMHeapAllocZ(pUsbIns, cb);
+}
+
+/**
+ * Frees memory allocated by PDMUsbHlpMMHeapAlloc or PDMUsbHlpMMHeapAllocZ.
+ *
+ * @param pUsbIns The USB device instance.
+ * @param pv The memory to free. NULL is fine.
+ */
+DECLINLINE(void) PDMUsbHlpMMHeapFree(PPDMUSBINS pUsbIns, void *pv)
+{
+ NOREF(pUsbIns);
+ MMR3HeapFree(pv);
+}
+
+/**
+ * @copydoc PDMUSBHLP::pfnTMTimerCreate
+ */
+DECLINLINE(int) PDMUsbHlpTMTimerCreate(PPDMUSBINS pUsbIns, TMCLOCK enmClock, PFNTMTIMERUSB pfnCallback, void *pvUser,
+ uint32_t fFlags, const char *pszDesc, PPTMTIMERR3 ppTimer)
+{
+ return pUsbIns->pHlpR3->pfnTMTimerCreate(pUsbIns, enmClock, pfnCallback, pvUser, fFlags, pszDesc, ppTimer);
+}
+
+#endif /* IN_RING3 */
+
+
+
+/** Pointer to callbacks provided to the VBoxUsbRegister() call. */
+typedef const struct PDMUSBREGCB *PCPDMUSBREGCB;
+
+/**
+ * Callbacks for VBoxUSBDeviceRegister().
+ */
+typedef struct PDMUSBREGCB
+{
+ /** Interface version.
+ * This is set to PDM_USBREG_CB_VERSION. */
+ uint32_t u32Version;
+
+ /**
+ * Registers a device with the current VM instance.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param pReg Pointer to the USB device registration record.
+ * This data must be permanent and readonly.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegister,(PCPDMUSBREGCB pCallbacks, PCPDMUSBREG pReg));
+} PDMUSBREGCB;
+
+/** Current version of the PDMUSBREGCB structure. */
+#define PDM_USBREG_CB_VERSION PDM_VERSION_MAKE(0xeefc, 1, 0)
+
+
+/**
+ * The VBoxUsbRegister callback function.
+ *
+ * PDM will invoke this function after loading a USB device module and letting
+ * the module decide which devices to register and how to handle conflicts.
+ *
+ * @returns VBox status code.
+ * @param pCallbacks Pointer to the callback table.
+ * @param u32Version VBox version number.
+ */
+typedef DECLCALLBACK(int) FNPDMVBOXUSBREGISTER(PCPDMUSBREGCB pCallbacks, uint32_t u32Version);
+
+VMMR3DECL(int) PDMR3USBCreateProxyDevice(PVM pVM, PCRTUUID pUuid, bool fRemote, const char *pszAddress, void *pvBackend,
+ uint32_t iUsbVersion, uint32_t fMaskedIfs);
+VMMR3DECL(int) PDMR3USBDetachDevice(PVM pVM, PCRTUUID pUuid);
+VMMR3DECL(bool) PDMR3USBHasHub(PVM pVM);
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
diff --git a/include/VBox/vmm/pgm.h b/include/VBox/vmm/pgm.h
new file mode 100644
index 00000000..5d8b5f0d
--- /dev/null
+++ b/include/VBox/vmm/pgm.h
@@ -0,0 +1,586 @@
+/** @file
+ * PGM - Page Monitor / Monitor.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_pgm_h
+#define ___VBox_vmm_pgm_h
+
+#include <VBox/types.h>
+#include <VBox/sup.h>
+#include <VBox/vmm/vmapi.h>
+#include <VBox/vmm/gmm.h> /* for PGMMREGISTERSHAREDMODULEREQ */
+#include <iprt/x86.h>
+#include <VBox/VMMDev.h> /* for VMMDEVSHAREDREGIONDESC */
+#include <VBox/param.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_pgm The Page Monitor / Manager API
+ * @{
+ */
+
+/**
+ * FNPGMRELOCATE callback mode.
+ */
+typedef enum PGMRELOCATECALL
+{
+ /** The callback is for checking if the suggested address is suitable. */
+ PGMRELOCATECALL_SUGGEST = 1,
+ /** The callback is for executing the relocation. */
+ PGMRELOCATECALL_RELOCATE
+} PGMRELOCATECALL;
+
+
+/**
+ * Callback function which will be called when PGM is trying to find
+ * a new location for the mapping.
+ *
+ * The callback is called in two modes, 1) the check mode and 2) the relocate mode.
+ * In 1) the callback should say if it objects to a suggested new location. If it
+ * accepts the new location, it is called again for doing it's relocation.
+ *
+ *
+ * @returns true if the location is ok.
+ * @returns false if another location should be found.
+ * @param GCPtrOld The old virtual address.
+ * @param GCPtrNew The new virtual address.
+ * @param enmMode Used to indicate the callback mode.
+ * @param pvUser User argument.
+ * @remark The return value is no a failure indicator, it's an acceptance
+ * indicator. Relocation can not fail!
+ */
+typedef DECLCALLBACK(bool) FNPGMRELOCATE(PVM pVM, RTGCPTR GCPtrOld, RTGCPTR GCPtrNew, PGMRELOCATECALL enmMode, void *pvUser);
+/** Pointer to a relocation callback function. */
+typedef FNPGMRELOCATE *PFNPGMRELOCATE;
+
+
+/**
+ * Physical page access handler type.
+ */
+typedef enum PGMPHYSHANDLERTYPE
+{
+ /** MMIO range. Pages are not present, all access is done in interpreter or recompiler. */
+ PGMPHYSHANDLERTYPE_MMIO = 1,
+ /** Handler all write access to a physical page range. */
+ PGMPHYSHANDLERTYPE_PHYSICAL_WRITE,
+ /** Handler all access to a physical page range. */
+ PGMPHYSHANDLERTYPE_PHYSICAL_ALL
+
+} PGMPHYSHANDLERTYPE;
+
+/**
+ * \#PF Handler callback for physical access handler ranges in RC.
+ *
+ * @returns VBox status code (appropriate for RC return).
+ * @param pVM VM Handle.
+ * @param uErrorCode CPU Error code.
+ * @param pRegFrame Trap register frame.
+ * NULL on DMA and other non CPU access.
+ * @param pvFault The fault address (cr2).
+ * @param GCPhysFault The GC physical address corresponding to pvFault.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACK(int) FNPGMRCPHYSHANDLER(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser);
+/** Pointer to PGM access callback. */
+typedef FNPGMRCPHYSHANDLER *PFNPGMRCPHYSHANDLER;
+
+/**
+ * \#PF Handler callback for physical access handler ranges in R0.
+ *
+ * @returns VBox status code (appropriate for R0 return).
+ * @param pVM VM Handle.
+ * @param uErrorCode CPU Error code.
+ * @param pRegFrame Trap register frame.
+ * NULL on DMA and other non CPU access.
+ * @param pvFault The fault address (cr2).
+ * @param GCPhysFault The GC physical address corresponding to pvFault.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACK(int) FNPGMR0PHYSHANDLER(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPHYS GCPhysFault, void *pvUser);
+/** Pointer to PGM access callback. */
+typedef FNPGMR0PHYSHANDLER *PFNPGMR0PHYSHANDLER;
+
+/**
+ * Guest Access type
+ */
+typedef enum PGMACCESSTYPE
+{
+ /** Read access. */
+ PGMACCESSTYPE_READ = 1,
+ /** Write access. */
+ PGMACCESSTYPE_WRITE
+} PGMACCESSTYPE;
+
+/**
+ * \#PF Handler callback for physical access handler ranges (MMIO among others) in HC.
+ *
+ * The handler can not raise any faults, it's mainly for monitoring write access
+ * to certain pages.
+ *
+ * @returns VINF_SUCCESS if the handler have carried out the operation.
+ * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
+ * @param pVM VM Handle.
+ * @param GCPhys The physical address the guest is writing to.
+ * @param pvPhys The HC mapping of that address.
+ * @param pvBuf What the guest is reading/writing.
+ * @param cbBuf How much it's reading/writing.
+ * @param enmAccessType The access type.
+ * @param pvUser User argument.
+ *
+ * @todo Add pVCpu, possibly replacing pVM.
+ */
+typedef DECLCALLBACK(int) FNPGMR3PHYSHANDLER(PVM pVM, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser);
+/** Pointer to PGM access callback. */
+typedef FNPGMR3PHYSHANDLER *PFNPGMR3PHYSHANDLER;
+
+
+/**
+ * Virtual access handler type.
+ */
+typedef enum PGMVIRTHANDLERTYPE
+{
+ /** Write access handled. */
+ PGMVIRTHANDLERTYPE_WRITE = 1,
+ /** All access handled. */
+ PGMVIRTHANDLERTYPE_ALL,
+ /** Hypervisor write access handled.
+ * This is used to catch the guest trying to write to LDT, TSS and any other
+ * system structure which the brain dead intel guys let unprivilegde code find. */
+ PGMVIRTHANDLERTYPE_HYPERVISOR
+} PGMVIRTHANDLERTYPE;
+
+/**
+ * \#PF Handler callback for virtual access handler ranges, RC.
+ *
+ * Important to realize that a physical page in a range can have aliases, and
+ * for ALL and WRITE handlers these will also trigger.
+ *
+ * @returns VBox status code (appropriate for GC return).
+ * @param pVM VM Handle.
+ * @param uErrorCode CPU Error code.
+ * @param pRegFrame Trap register frame.
+ * @param pvFault The fault address (cr2).
+ * @param pvRange The base address of the handled virtual range.
+ * @param offRange The offset of the access into this range.
+ * (If it's a EIP range this is the EIP, if not it's pvFault.)
+ * @todo Add pVCpu, possibly replacing pVM.
+ */
+typedef DECLCALLBACK(int) FNPGMRCVIRTHANDLER(PVM pVM, RTGCUINT uErrorCode, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault, RTGCPTR pvRange, uintptr_t offRange);
+/** Pointer to PGM access callback. */
+typedef FNPGMRCVIRTHANDLER *PFNPGMRCVIRTHANDLER;
+
+/**
+ * \#PF Handler callback for virtual access handler ranges, R3.
+ *
+ * Important to realize that a physical page in a range can have aliases, and
+ * for ALL and WRITE handlers these will also trigger.
+ *
+ * @returns VINF_SUCCESS if the handler have carried out the operation.
+ * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
+ * @param pVM VM Handle.
+ * @param GCPtr The virtual address the guest is writing to. (not correct if it's an alias!)
+ * @param pvPtr The HC mapping of that address.
+ * @param pvBuf What the guest is reading/writing.
+ * @param cbBuf How much it's reading/writing.
+ * @param enmAccessType The access type.
+ * @param pvUser User argument.
+ * @todo Add pVCpu, possibly replacing pVM.
+ */
+typedef DECLCALLBACK(int) FNPGMR3VIRTHANDLER(PVM pVM, RTGCPTR GCPtr, void *pvPtr, void *pvBuf, size_t cbBuf, PGMACCESSTYPE enmAccessType, void *pvUser);
+/** Pointer to PGM access callback. */
+typedef FNPGMR3VIRTHANDLER *PFNPGMR3VIRTHANDLER;
+
+
+/**
+ * \#PF Handler callback for invalidation of virtual access handler ranges.
+ *
+ * @param pVM VM Handle.
+ * @param GCPtr The virtual address the guest has changed.
+ */
+typedef DECLCALLBACK(int) FNPGMR3VIRTINVALIDATE(PVM pVM, RTGCPTR GCPtr);
+/** Pointer to PGM invalidation callback. */
+typedef FNPGMR3VIRTINVALIDATE *PFNPGMR3VIRTINVALIDATE;
+
+/**
+ * PGMR3PhysEnumDirtyFTPages callback for syncing dirty physical pages
+ *
+ * @param pVM VM Handle.
+ * @param GCPhys GC physical address
+ * @param pRange HC virtual address of the page(s)
+ * @param cbRange Size of the dirty range in bytes.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACK(int) FNPGMENUMDIRTYFTPAGES(PVM pVM, RTGCPHYS GCPhys, uint8_t *pRange, unsigned cbRange, void *pvUser);
+/** Pointer to PGMR3PhysEnumDirtyFTPages callback. */
+typedef FNPGMENUMDIRTYFTPAGES *PFNPGMENUMDIRTYFTPAGES;
+
+/**
+ * Paging mode.
+ */
+typedef enum PGMMODE
+{
+ /** The usual invalid value. */
+ PGMMODE_INVALID = 0,
+ /** Real mode. */
+ PGMMODE_REAL,
+ /** Protected mode, no paging. */
+ PGMMODE_PROTECTED,
+ /** 32-bit paging. */
+ PGMMODE_32_BIT,
+ /** PAE paging. */
+ PGMMODE_PAE,
+ /** PAE paging with NX enabled. */
+ PGMMODE_PAE_NX,
+ /** 64-bit AMD paging (long mode). */
+ PGMMODE_AMD64,
+ /** 64-bit AMD paging (long mode) with NX enabled. */
+ PGMMODE_AMD64_NX,
+ /** Nested paging mode (shadow only; guest physical to host physical). */
+ PGMMODE_NESTED,
+ /** Extended paging (Intel) mode. */
+ PGMMODE_EPT,
+ /** The max number of modes */
+ PGMMODE_MAX,
+ /** 32bit hackishness. */
+ PGMMODE_32BIT_HACK = 0x7fffffff
+} PGMMODE;
+
+/** Macro for checking if the guest is using paging.
+ * @param enmMode PGMMODE_*.
+ * @remark ASSUMES certain order of the PGMMODE_* values.
+ */
+#define PGMMODE_WITH_PAGING(enmMode) ((enmMode) >= PGMMODE_32_BIT)
+
+/** Macro for checking if it's one of the long mode modes.
+ * @param enmMode PGMMODE_*.
+ */
+#define PGMMODE_IS_LONG_MODE(enmMode) ((enmMode) == PGMMODE_AMD64_NX || (enmMode) == PGMMODE_AMD64)
+
+/**
+ * Is the ROM mapped (true) or is the shadow RAM mapped (false).
+ *
+ * @returns boolean.
+ * @param enmProt The PGMROMPROT value, must be valid.
+ */
+#define PGMROMPROT_IS_ROM(enmProt) \
+ ( (enmProt) == PGMROMPROT_READ_ROM_WRITE_IGNORE \
+ || (enmProt) == PGMROMPROT_READ_ROM_WRITE_RAM )
+
+
+
+VMMDECL(bool) PGMIsLockOwner(PVM pVM);
+
+VMMDECL(int) PGMRegisterStringFormatTypes(void);
+VMMDECL(void) PGMDeregisterStringFormatTypes(void);
+VMMDECL(RTHCPHYS) PGMGetHyperCR3(PVMCPU pVCpu);
+VMMDECL(RTHCPHYS) PGMGetNestedCR3(PVMCPU pVCpu, PGMMODE enmShadowMode);
+VMMDECL(RTHCPHYS) PGMGetInterHCCR3(PVM pVM);
+VMMDECL(RTHCPHYS) PGMGetInterRCCR3(PVM pVM, PVMCPU pVCpu);
+VMMDECL(RTHCPHYS) PGMGetInter32BitCR3(PVM pVM);
+VMMDECL(RTHCPHYS) PGMGetInterPaeCR3(PVM pVM);
+VMMDECL(RTHCPHYS) PGMGetInterAmd64CR3(PVM pVM);
+VMMDECL(int) PGMTrap0eHandler(PVMCPU pVCpu, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault);
+VMMDECL(int) PGMPrefetchPage(PVMCPU pVCpu, RTGCPTR GCPtrPage);
+VMMDECL(int) PGMVerifyAccess(PVMCPU pVCpu, RTGCPTR Addr, uint32_t cbSize, uint32_t fAccess);
+VMMDECL(int) PGMIsValidAccess(PVMCPU pVCpu, RTGCPTR Addr, uint32_t cbSize, uint32_t fAccess);
+VMMDECL(VBOXSTRICTRC) PGMInterpretInstruction(PVM pVM, PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, RTGCPTR pvFault);
+VMMDECL(int) PGMMap(PVM pVM, RTGCPTR GCPtr, RTHCPHYS HCPhys, uint32_t cbPages, unsigned fFlags);
+VMMDECL(int) PGMMapGetPage(PVM pVM, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys);
+VMMDECL(int) PGMMapSetPage(PVM pVM, RTGCPTR GCPtr, uint64_t cb, uint64_t fFlags);
+VMMDECL(int) PGMMapModifyPage(PVM pVM, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask);
+#ifndef IN_RING0
+VMMDECL(bool) PGMMapHasConflicts(PVM pVM);
+#endif
+#ifdef VBOX_STRICT
+VMMDECL(void) PGMMapCheck(PVM pVM);
+#endif
+VMMDECL(int) PGMShwGetPage(PVMCPU pVCpu, RTGCPTR GCPtr, uint64_t *pfFlags, PRTHCPHYS pHCPhys);
+VMMDECL(int) PGMShwMakePageReadonly(PVMCPU pVCpu, RTGCPTR GCPtr, uint32_t fFlags);
+VMMDECL(int) PGMShwMakePageWritable(PVMCPU pVCpu, RTGCPTR GCPtr, uint32_t fFlags);
+VMMDECL(int) PGMShwMakePageNotPresent(PVMCPU pVCpu, RTGCPTR GCPtr, uint32_t fFlags);
+/** @name Flags for PGMShwMakePageReadonly, PGMShwMakePageWritable and
+ * PGMShwMakePageNotPresent
+ * @{ */
+/** The call is from an access handler for dealing with the a faulting write
+ * operation. The virtual address is within the same page. */
+#define PGM_MK_PG_IS_WRITE_FAULT RT_BIT(0)
+/** The page is an MMIO2. */
+#define PGM_MK_PG_IS_MMIO2 RT_BIT(1)
+/** @}*/
+VMMDECL(int) PGMGstGetPage(PVMCPU pVCpu, RTGCPTR GCPtr, uint64_t *pfFlags, PRTGCPHYS pGCPhys);
+VMMDECL(bool) PGMGstIsPagePresent(PVMCPU pVCpu, RTGCPTR GCPtr);
+VMMDECL(int) PGMGstSetPage(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags);
+VMMDECL(int) PGMGstModifyPage(PVMCPU pVCpu, RTGCPTR GCPtr, size_t cb, uint64_t fFlags, uint64_t fMask);
+VMM_INT_DECL(int) PGMGstGetPaePdpes(PVMCPU pVCpu, PX86PDPE paPdpes);
+VMM_INT_DECL(int) PGMGstUpdatePaePdpes(PVMCPU pVCpu, PCX86PDPE paPdpes);
+
+VMMDECL(int) PGMInvalidatePage(PVMCPU pVCpu, RTGCPTR GCPtrPage);
+VMMDECL(int) PGMFlushTLB(PVMCPU pVCpu, uint64_t cr3, bool fGlobal);
+VMMDECL(int) PGMSyncCR3(PVMCPU pVCpu, uint64_t cr0, uint64_t cr3, uint64_t cr4, bool fGlobal);
+VMMDECL(int) PGMUpdateCR3(PVMCPU pVCpu, uint64_t cr3);
+VMMDECL(int) PGMChangeMode(PVMCPU pVCpu, uint64_t cr0, uint64_t cr4, uint64_t efer);
+VMMDECL(PGMMODE) PGMGetGuestMode(PVMCPU pVCpu);
+VMMDECL(PGMMODE) PGMGetShadowMode(PVMCPU pVCpu);
+VMMDECL(PGMMODE) PGMGetHostMode(PVM pVM);
+VMMDECL(const char *) PGMGetModeName(PGMMODE enmMode);
+VMM_INT_DECL(void) PGMNotifyNxeChanged(PVMCPU pVCpu, bool fNxe);
+VMMDECL(bool) PGMHasDirtyPages(PVM pVM);
+VMMDECL(int) PGMHandlerPhysicalRegisterEx(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast,
+ R3PTRTYPE(PFNPGMR3PHYSHANDLER) pfnHandlerR3, RTR3PTR pvUserR3,
+ R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnHandlerR0, RTR0PTR pvUserR0,
+ RCPTRTYPE(PFNPGMRCPHYSHANDLER) pfnHandlerRC, RTRCPTR pvUserRC,
+ R3PTRTYPE(const char *) pszDesc);
+VMMDECL(int) PGMHandlerPhysicalModify(PVM pVM, RTGCPHYS GCPhysCurrent, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast);
+VMMDECL(int) PGMHandlerPhysicalDeregister(PVM pVM, RTGCPHYS GCPhys);
+VMMDECL(int) PGMHandlerPhysicalChangeCallbacks(PVM pVM, RTGCPHYS GCPhys,
+ R3PTRTYPE(PFNPGMR3PHYSHANDLER) pfnHandlerR3, RTR3PTR pvUserR3,
+ R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnHandlerR0, RTR0PTR pvUserR0,
+ RCPTRTYPE(PFNPGMRCPHYSHANDLER) pfnHandlerRC, RTRCPTR pvUserRC,
+ R3PTRTYPE(const char *) pszDesc);
+VMMDECL(int) PGMHandlerPhysicalSplit(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysSplit);
+VMMDECL(int) PGMHandlerPhysicalJoin(PVM pVM, RTGCPHYS GCPhys1, RTGCPHYS GCPhys2);
+VMMDECL(int) PGMHandlerPhysicalPageTempOff(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage);
+VMMDECL(int) PGMHandlerPhysicalPageAlias(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage, RTGCPHYS GCPhysPageRemap);
+VMMDECL(int) PGMHandlerPhysicalPageAliasHC(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage, RTHCPHYS HCPhysPageRemap);
+VMMDECL(int) PGMHandlerPhysicalReset(PVM pVM, RTGCPHYS GCPhys);
+VMMDECL(bool) PGMHandlerPhysicalIsRegistered(PVM pVM, RTGCPHYS GCPhys);
+VMMDECL(bool) PGMHandlerVirtualIsRegistered(PVM pVM, RTGCPTR GCPtr);
+VMMDECL(bool) PGMPhysIsA20Enabled(PVMCPU pVCpu);
+VMMDECL(bool) PGMPhysIsGCPhysValid(PVM pVM, RTGCPHYS GCPhys);
+VMMDECL(bool) PGMPhysIsGCPhysNormal(PVM pVM, RTGCPHYS GCPhys);
+VMMDECL(int) PGMPhysGCPtr2GCPhys(PVMCPU pVCpu, RTGCPTR GCPtr, PRTGCPHYS pGCPhys);
+VMMDECL(void) PGMPhysReleasePageMappingLock(PVM pVM, PPGMPAGEMAPLOCK pLock);
+VMMDECL(int) PGMPhysRead(PVM pVM, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead);
+VMMDECL(int) PGMPhysWrite(PVM pVM, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite);
+VMMDECL(int) PGMPhysSimpleReadGCPhys(PVM pVM, void *pvDst, RTGCPHYS GCPhysSrc, size_t cb);
+VMMDECL(int) PGMPhysSimpleWriteGCPhys(PVM pVM, RTGCPHYS GCPhysDst, const void *pvSrc, size_t cb);
+VMMDECL(int) PGMPhysSimpleReadGCPtr(PVMCPU pVCpu, void *pvDst, RTGCPTR GCPtrSrc, size_t cb);
+VMMDECL(int) PGMPhysSimpleWriteGCPtr(PVMCPU pVCpu, RTGCPTR GCPtrDst, const void *pvSrc, size_t cb);
+VMMDECL(int) PGMPhysReadGCPtr(PVMCPU pVCpu, void *pvDst, RTGCPTR GCPtrSrc, size_t cb);
+VMMDECL(int) PGMPhysWriteGCPtr(PVMCPU pVCpu, RTGCPTR GCPtrDst, const void *pvSrc, size_t cb);
+VMMDECL(int) PGMPhysSimpleDirtyWriteGCPtr(PVMCPU pVCpu, RTGCPTR GCPtrDst, const void *pvSrc, size_t cb);
+VMMDECL(int) PGMPhysInterpretedRead(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, void *pvDst, RTGCPTR GCPtrSrc, size_t cb);
+VMMDECL(int) PGMPhysInterpretedReadNoHandlers(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, void *pvDst, RTGCUINTPTR GCPtrSrc, size_t cb, bool fRaiseTrap);
+VMMDECL(int) PGMPhysInterpretedWriteNoHandlers(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, RTGCPTR GCPtrDst, void const *pvSrc, size_t cb, bool fRaiseTrap);
+VMM_INT_DECL(int) PGMPhysIemGCPhys2Ptr(PVM pVM, RTGCPHYS GCPhys, bool fWritable, bool fByPassHandlers, void **ppv, PPGMPAGEMAPLOCK pLock);
+#ifdef VBOX_STRICT
+VMMDECL(unsigned) PGMAssertHandlerAndFlagsInSync(PVM pVM);
+VMMDECL(unsigned) PGMAssertNoMappingConflicts(PVM pVM);
+VMMDECL(unsigned) PGMAssertCR3(PVM pVM, PVMCPU pVCpu, uint64_t cr3, uint64_t cr4);
+#endif /* VBOX_STRICT */
+
+#if defined(IN_RC) || defined(VBOX_WITH_2X_4GB_ADDR_SPACE)
+VMMDECL(void) PGMRZDynMapStartAutoSet(PVMCPU pVCpu);
+VMMDECL(void) PGMRZDynMapReleaseAutoSet(PVMCPU pVCpu);
+VMMDECL(void) PGMRZDynMapFlushAutoSet(PVMCPU pVCpu);
+VMMDECL(uint32_t) PGMRZDynMapPushAutoSubset(PVMCPU pVCpu);
+VMMDECL(void) PGMRZDynMapPopAutoSubset(PVMCPU pVCpu, uint32_t iPrevSubset);
+#endif
+
+VMMDECL(int) PGMSetLargePageUsage(PVM pVM, bool fUseLargePages);
+
+/**
+ * Query large page usage state
+ *
+ * @returns 0 - disabled, 1 - enabled
+ * @param pVM The VM to operate on.
+ */
+#define PGMIsUsingLargePages(pVM) ((pVM)->fUseLargePages)
+
+
+#ifdef IN_RC
+/** @defgroup grp_pgm_gc The PGM Guest Context API
+ * @ingroup grp_pgm
+ * @{
+ */
+VMMRCDECL(int) PGMRCDynMapInit(PVM pVM);
+/** @} */
+#endif /* IN_RC */
+
+
+#ifdef IN_RING0
+/** @defgroup grp_pgm_r0 The PGM Host Context Ring-0 API
+ * @ingroup grp_pgm
+ * @{
+ */
+VMMR0_INT_DECL(int) PGMR0PhysAllocateHandyPages(PVM pVM, PVMCPU pVCpu);
+VMMR0_INT_DECL(int) PGMR0PhysFlushHandyPages(PVM pVM, PVMCPU pVCpu);
+VMMR0_INT_DECL(int) PGMR0PhysAllocateLargeHandyPage(PVM pVM, PVMCPU pVCpu);
+VMMR0_INT_DECL(int) PGMR0PhysSetupIommu(PVM pVM);
+VMMR0DECL(int) PGMR0SharedModuleCheck(PVM pVM, PGVM pGVM, VMCPUID idCpu, PGMMSHAREDMODULE pModule, PCRTGCPTR64 paRegionsGCPtrs);
+VMMR0DECL(int) PGMR0Trap0eHandlerNestedPaging(PVM pVM, PVMCPU pVCpu, PGMMODE enmShwPagingMode, RTGCUINT uErr, PCPUMCTXCORE pRegFrame, RTGCPHYS pvFault);
+VMMR0DECL(VBOXSTRICTRC) PGMR0Trap0eHandlerNPMisconfig(PVM pVM, PVMCPU pVCpu, PGMMODE enmShwPagingMode, PCPUMCTXCORE pRegFrame, RTGCPHYS GCPhysFault, uint32_t uErr);
+# ifdef VBOX_WITH_2X_4GB_ADDR_SPACE
+VMMR0DECL(int) PGMR0DynMapInit(void);
+VMMR0DECL(void) PGMR0DynMapTerm(void);
+VMMR0DECL(int) PGMR0DynMapInitVM(PVM pVM);
+VMMR0DECL(void) PGMR0DynMapTermVM(PVM pVM);
+VMMR0DECL(int) PGMR0DynMapAssertIntegrity(void);
+VMMR0DECL(bool) PGMR0DynMapStartOrMigrateAutoSet(PVMCPU pVCpu);
+VMMR0DECL(void) PGMR0DynMapMigrateAutoSet(PVMCPU pVCpu);
+# endif
+/** @} */
+#endif /* IN_RING0 */
+
+
+
+#ifdef IN_RING3
+/** @defgroup grp_pgm_r3 The PGM Host Context Ring-3 API
+ * @ingroup grp_pgm
+ * @{
+ */
+VMMR3DECL(int) PGMR3Init(PVM pVM);
+VMMR3DECL(int) PGMR3InitDynMap(PVM pVM);
+VMMR3DECL(int) PGMR3InitFinalize(PVM pVM);
+VMMR3_INT_DECL(int) PGMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
+VMMR3DECL(void) PGMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3DECL(void) PGMR3ResetUnpluggedCpu(PVM pVM, PVMCPU pVCpu);
+VMMR3DECL(void) PGMR3Reset(PVM pVM);
+VMMR3DECL(int) PGMR3Term(PVM pVM);
+VMMR3DECL(int) PGMR3LockCall(PVM pVM);
+VMMR3DECL(int) PGMR3ChangeMode(PVM pVM, PVMCPU pVCpu, PGMMODE enmGuestMode);
+
+VMMR3DECL(int) PGMR3PhysRegisterRam(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, const char *pszDesc);
+VMMR3DECL(int) PGMR3PhysChangeMemBalloon(PVM pVM, bool fInflate, unsigned cPages, RTGCPHYS *paPhysPage);
+VMMR3DECL(int) PGMR3PhysWriteProtectRAM(PVM pVM);
+VMMR3DECL(int) PGMR3PhysEnumDirtyFTPages(PVM pVM, PFNPGMENUMDIRTYFTPAGES pfnEnum, void *pvUser);
+VMMR3DECL(uint32_t) PGMR3PhysGetRamRangeCount(PVM pVM);
+VMMR3DECL(int) PGMR3PhysGetRange(PVM pVM, uint32_t iRange, PRTGCPHYS pGCPhysStart, PRTGCPHYS pGCPhysLast,
+ const char **ppszDesc, bool *pfIsMmio);
+VMMR3DECL(int) PGMR3QueryMemoryStats(PVM pVM, uint64_t *pcbTotalMem, uint64_t *pcbPrivateMem, uint64_t *pcbSharedMem, uint64_t *pcbZeroMem);
+VMMR3DECL(int) PGMR3QueryGlobalMemoryStats(PVM pVM, uint64_t *pcbAllocMem, uint64_t *pcbFreeMem, uint64_t *pcbBallonedMem, uint64_t *pcbSharedMem);
+
+VMMR3DECL(int) PGMR3PhysMMIORegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb,
+ R3PTRTYPE(PFNPGMR3PHYSHANDLER) pfnHandlerR3, RTR3PTR pvUserR3,
+ R0PTRTYPE(PFNPGMR0PHYSHANDLER) pfnHandlerR0, RTR0PTR pvUserR0,
+ RCPTRTYPE(PFNPGMRCPHYSHANDLER) pfnHandlerRC, RTRCPTR pvUserRC,
+ R3PTRTYPE(const char *) pszDesc);
+VMMR3DECL(int) PGMR3PhysMMIODeregister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb);
+VMMR3DECL(int) PGMR3PhysMMIO2Register(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS cb, uint32_t fFlags, void **ppv, const char *pszDesc);
+VMMR3DECL(int) PGMR3PhysMMIO2Deregister(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion);
+VMMR3DECL(int) PGMR3PhysMMIO2Map(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys);
+VMMR3DECL(int) PGMR3PhysMMIO2Unmap(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS GCPhys);
+VMMR3DECL(bool) PGMR3PhysMMIO2IsBase(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys);
+VMMR3DECL(int) PGMR3PhysMMIO2GetHCPhys(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, PRTHCPHYS pHCPhys);
+VMMR3DECL(int) PGMR3PhysMMIO2MapKernel(PVM pVM, PPDMDEVINS pDevIns, uint32_t iRegion, RTGCPHYS off, RTGCPHYS cb, const char *pszDesc, PRTR0PTR pR0Ptr);
+
+/** @name PGMR3PhysRegisterRom flags.
+ * @{ */
+/** Inidicates that ROM shadowing should be enabled. */
+#define PGMPHYS_ROM_FLAGS_SHADOWED RT_BIT_32(0)
+/** Indicates that what pvBinary points to won't go away
+ * and can be used for strictness checks. */
+#define PGMPHYS_ROM_FLAGS_PERMANENT_BINARY RT_BIT_32(1)
+/** @} */
+
+VMMR3DECL(int) PGMR3PhysRomRegister(PVM pVM, PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS cb,
+ const void *pvBinary, uint32_t cbBinary, uint32_t fFlags, const char *pszDesc);
+VMMR3DECL(int) PGMR3PhysRomProtect(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, PGMROMPROT enmProt);
+VMMR3DECL(int) PGMR3PhysRegister(PVM pVM, void *pvRam, RTGCPHYS GCPhys, size_t cb, unsigned fFlags, const SUPPAGE *paPages, const char *pszDesc);
+VMMDECL(void) PGMR3PhysSetA20(PVMCPU pVCpu, bool fEnable);
+/** @name PGMR3MapPT flags.
+ * @{ */
+/** The mapping may be unmapped later. The default is permanent mappings. */
+#define PGMR3MAPPT_FLAGS_UNMAPPABLE RT_BIT(0)
+/** @} */
+VMMR3DECL(int) PGMR3MapPT(PVM pVM, RTGCPTR GCPtr, uint32_t cb, uint32_t fFlags, PFNPGMRELOCATE pfnRelocate, void *pvUser, const char *pszDesc);
+VMMR3DECL(int) PGMR3UnmapPT(PVM pVM, RTGCPTR GCPtr);
+VMMR3DECL(int) PGMR3FinalizeMappings(PVM pVM);
+VMMR3DECL(int) PGMR3MappingsDisable(PVM pVM);
+VMMR3DECL(int) PGMR3MappingsSize(PVM pVM, uint32_t *pcb);
+VMMR3DECL(int) PGMR3MappingsFix(PVM pVM, RTGCPTR GCPtrBase, uint32_t cb);
+VMMR3DECL(int) PGMR3MappingsUnfix(PVM pVM);
+VMMR3DECL(bool) PGMR3MappingsNeedReFixing(PVM pVM);
+VMMR3DECL(int) PGMR3MapIntermediate(PVM pVM, RTUINTPTR Addr, RTHCPHYS HCPhys, unsigned cbPages);
+VMMR3DECL(int) PGMR3MapRead(PVM pVM, void *pvDst, RTGCPTR GCPtrSrc, size_t cb);
+
+VMMR3DECL(int) PGMR3HandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast,
+ PFNPGMR3PHYSHANDLER pfnHandlerR3, void *pvUserR3,
+ const char *pszModR0, const char *pszHandlerR0, RTR0PTR pvUserR0,
+ const char *pszModRC, const char *pszHandlerRC, RTRCPTR pvUserRC, const char *pszDesc);
+VMMDECL(int) PGMR3HandlerVirtualRegisterEx(PVM pVM, PGMVIRTHANDLERTYPE enmType, RTGCPTR GCPtr, RTGCPTR GCPtrLast,
+ R3PTRTYPE(PFNPGMR3VIRTINVALIDATE) pfnInvalidateR3,
+ R3PTRTYPE(PFNPGMR3VIRTHANDLER) pfnHandlerR3,
+ RCPTRTYPE(PFNPGMRCVIRTHANDLER) pfnHandlerRC,
+ R3PTRTYPE(const char *) pszDesc);
+VMMR3DECL(int) PGMR3HandlerVirtualRegister(PVM pVM, PGMVIRTHANDLERTYPE enmType, RTGCPTR GCPtr, RTGCPTR GCPtrLast,
+ PFNPGMR3VIRTINVALIDATE pfnInvalidateR3,
+ PFNPGMR3VIRTHANDLER pfnHandlerR3,
+ const char *pszHandlerRC, const char *pszModRC, const char *pszDesc);
+VMMDECL(int) PGMHandlerVirtualChangeInvalidateCallback(PVM pVM, RTGCPTR GCPtr, R3PTRTYPE(PFNPGMR3VIRTINVALIDATE) pfnInvalidateR3);
+VMMDECL(int) PGMHandlerVirtualDeregister(PVM pVM, RTGCPTR GCPtr);
+VMMR3DECL(int) PGMR3PoolGrow(PVM pVM);
+
+VMMR3DECL(int) PGMR3PhysTlbGCPhys2Ptr(PVM pVM, RTGCPHYS GCPhys, bool fWritable, void **ppv);
+VMMR3DECL(uint8_t) PGMR3PhysReadU8(PVM pVM, RTGCPHYS GCPhys);
+VMMR3DECL(uint16_t) PGMR3PhysReadU16(PVM pVM, RTGCPHYS GCPhys);
+VMMR3DECL(uint32_t) PGMR3PhysReadU32(PVM pVM, RTGCPHYS GCPhys);
+VMMR3DECL(uint64_t) PGMR3PhysReadU64(PVM pVM, RTGCPHYS GCPhys);
+VMMR3DECL(void) PGMR3PhysWriteU8(PVM pVM, RTGCPHYS GCPhys, uint8_t Value);
+VMMR3DECL(void) PGMR3PhysWriteU16(PVM pVM, RTGCPHYS GCPhys, uint16_t Value);
+VMMR3DECL(void) PGMR3PhysWriteU32(PVM pVM, RTGCPHYS GCPhys, uint32_t Value);
+VMMR3DECL(void) PGMR3PhysWriteU64(PVM pVM, RTGCPHYS GCPhys, uint64_t Value);
+VMMR3DECL(int) PGMR3PhysReadExternal(PVM pVM, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead);
+VMMR3DECL(int) PGMR3PhysWriteExternal(PVM pVM, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, const char *pszWho);
+VMMR3DECL(int) PGMR3PhysGCPhys2CCPtrExternal(PVM pVM, RTGCPHYS GCPhys, void **ppv, PPGMPAGEMAPLOCK pLock);
+VMMR3DECL(int) PGMR3PhysGCPhys2CCPtrReadOnlyExternal(PVM pVM, RTGCPHYS GCPhys, void const **ppv, PPGMPAGEMAPLOCK pLock);
+VMMR3DECL(int) PGMR3PhysChunkMap(PVM pVM, uint32_t idChunk);
+VMMR3DECL(void) PGMR3PhysChunkInvalidateTLB(PVM pVM);
+VMMR3DECL(int) PGMR3PhysAllocateHandyPages(PVM pVM);
+VMMR3DECL(int) PGMR3PhysAllocateLargeHandyPage(PVM pVM, RTGCPHYS GCPhys);
+
+VMMR3DECL(int) PGMR3CheckIntegrity(PVM pVM);
+
+VMMR3DECL(int) PGMR3DbgR3Ptr2GCPhys(PVM pVM, RTR3PTR R3Ptr, PRTGCPHYS pGCPhys);
+VMMR3DECL(int) PGMR3DbgR3Ptr2HCPhys(PVM pVM, RTR3PTR R3Ptr, PRTHCPHYS pHCPhys);
+VMMR3DECL(int) PGMR3DbgHCPhys2GCPhys(PVM pVM, RTHCPHYS HCPhys, PRTGCPHYS pGCPhys);
+VMMR3DECL(int) PGMR3DbgReadGCPhys(PVM pVM, void *pvDst, RTGCPHYS GCPhysSrc, size_t cb, uint32_t fFlags, size_t *pcbRead);
+VMMR3DECL(int) PGMR3DbgWriteGCPhys(PVM pVM, RTGCPHYS GCPhysDst, const void *pvSrc, size_t cb, uint32_t fFlags, size_t *pcbWritten);
+VMMR3DECL(int) PGMR3DbgReadGCPtr(PVM pVM, void *pvDst, RTGCPTR GCPtrSrc, size_t cb, uint32_t fFlags, size_t *pcbRead);
+VMMR3DECL(int) PGMR3DbgWriteGCPtr(PVM pVM, RTGCPTR GCPtrDst, void const *pvSrc, size_t cb, uint32_t fFlags, size_t *pcbWritten);
+VMMR3DECL(int) PGMR3DbgScanPhysical(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cbRange, RTGCPHYS GCPhysAlign, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCPHYS pGCPhysHit);
+VMMR3DECL(int) PGMR3DbgScanVirtual(PVM pVM, PVMCPU pVCpu, RTGCPTR GCPtr, RTGCPTR cbRange, RTGCPTR GCPtrAlign, const uint8_t *pabNeedle, size_t cbNeedle, PRTGCUINTPTR pGCPhysHit);
+VMMR3_INT_DECL(int) PGMR3DumpHierarchyShw(PVM pVM, uint64_t cr3, uint32_t fFlags, uint64_t u64FirstAddr, uint64_t u64LastAddr, uint32_t cMaxDepth, PCDBGFINFOHLP pHlp);
+VMMR3_INT_DECL(int) PGMR3DumpHierarchyGst(PVM pVM, uint64_t cr3, uint32_t fFlags, RTGCPTR FirstAddr, RTGCPTR LastAddr, uint32_t cMaxDepth, PCDBGFINFOHLP pHlp);
+
+
+/** @name Page sharing
+ * @{ */
+VMMR3DECL(int) PGMR3SharedModuleRegister(PVM pVM, VBOXOSFAMILY enmGuestOS, char *pszModuleName, char *pszVersion,
+ RTGCPTR GCBaseAddr, uint32_t cbModule,
+ uint32_t cRegions, VMMDEVSHAREDREGIONDESC const *paRegions);
+VMMR3DECL(int) PGMR3SharedModuleUnregister(PVM pVM, char *pszModuleName, char *pszVersion,
+ RTGCPTR GCBaseAddr, uint32_t cbModule);
+VMMR3DECL(int) PGMR3SharedModuleCheckAll(PVM pVM);
+VMMR3DECL(int) PGMR3SharedModuleGetPageState(PVM pVM, RTGCPTR GCPtrPage, bool *pfShared, uint64_t *pfPageFlags);
+/** @} */
+
+/** @} */
+#endif /* IN_RING3 */
+
+RT_C_DECLS_END
+
+/** @} */
+#endif
+
diff --git a/include/VBox/vmm/rem.h b/include/VBox/vmm/rem.h
new file mode 100644
index 00000000..79a18810
--- /dev/null
+++ b/include/VBox/vmm/rem.h
@@ -0,0 +1,106 @@
+/** @file
+ * REM - The Recompiled Execution Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_rem_h
+#define ___VBox_vmm_rem_h
+
+#include <VBox/types.h>
+#include <VBox/vmm/pgm.h>
+#include <VBox/vmm/vmapi.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_rem The Recompiled Execution Manager API
+ * @{
+ */
+
+/** No pending interrupt. */
+#define REM_NO_PENDING_IRQ (~(uint32_t)0)
+
+
+#if defined(IN_RING0) || defined(IN_RC)
+VMMDECL(void) REMNotifyInvalidatePage(PVM pVM, RTGCPTR GCPtrPage);
+VMMDECL(void) REMNotifyHandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler);
+VMMDECL(void) REMNotifyHandlerPhysicalDeregister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM);
+VMMDECL(void) REMNotifyHandlerPhysicalModify(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhysOld, RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM);
+#endif /* IN_RING0 || IN_RC */
+#ifdef IN_RC
+VMMDECL(void) REMNotifyHandlerPhysicalFlushIfAlmostFull(PVM pVM, PVMCPU pVCpu);
+#endif
+VMMDECL(void) REMFlushTBs(PVM pVM);
+
+
+#ifdef IN_RING3
+/** @defgroup grp_rem_r3 REM Host Context Ring 3 API
+ * @ingroup grp_rem
+ * @{
+ */
+REMR3DECL(int) REMR3Init(PVM pVM);
+REMR3DECL(int) REMR3InitFinalize(PVM pVM);
+REMR3DECL(int) REMR3Term(PVM pVM);
+REMR3DECL(void) REMR3Reset(PVM pVM);
+REMR3DECL(int) REMR3Run(PVM pVM, PVMCPU pVCpu);
+REMR3DECL(int) REMR3EmulateInstruction(PVM pVM, PVMCPU pVCpu);
+REMR3DECL(int) REMR3Step(PVM pVM, PVMCPU pVCpu);
+REMR3DECL(int) REMR3BreakpointSet(PVM pVM, RTGCUINTPTR Address);
+REMR3DECL(int) REMR3BreakpointClear(PVM pVM, RTGCUINTPTR Address);
+REMR3DECL(int) REMR3State(PVM pVM, PVMCPU pVCpu);
+REMR3DECL(int) REMR3StateBack(PVM pVM, PVMCPU pVCpu);
+REMR3DECL(void) REMR3StateUpdate(PVM pVM, PVMCPU pVCpu);
+REMR3DECL(void) REMR3A20Set(PVM pVM, PVMCPU pVCpu, bool fEnable);
+REMR3DECL(int) REMR3DisasEnableStepping(PVM pVM, bool fEnable);
+REMR3DECL(void) REMR3ReplayHandlerNotifications(PVM pVM);
+REMR3DECL(int) REMR3NotifyCodePageChanged(PVM pVM, PVMCPU pVCpu, RTGCPTR pvCodePage);
+REMR3DECL(void) REMR3NotifyPhysRamRegister(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, unsigned fFlags);
+/** @name Flags for REMR3NotifyPhysRamRegister.
+ * @{ */
+#define REM_NOTIFY_PHYS_RAM_FLAGS_RAM RT_BIT(16)
+#define REM_NOTIFY_PHYS_RAM_FLAGS_MMIO2 RT_BIT(17)
+/** @} */
+REMR3DECL(void) REMR3NotifyPhysRomRegister(PVM pVM, RTGCPHYS GCPhys, RTUINT cb, void *pvCopy, bool fShadow);
+REMR3DECL(void) REMR3NotifyPhysRamDeregister(PVM pVM, RTGCPHYS GCPhys, RTUINT cb);
+REMR3DECL(void) REMR3NotifyHandlerPhysicalRegister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler);
+REMR3DECL(void) REMR3NotifyHandlerPhysicalDeregister(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhys, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM);
+REMR3DECL(void) REMR3NotifyHandlerPhysicalModify(PVM pVM, PGMPHYSHANDLERTYPE enmType, RTGCPHYS GCPhysOld, RTGCPHYS GCPhysNew, RTGCPHYS cb, bool fHasHCHandler, bool fRestoreAsRAM);
+REMR3DECL(void) REMR3NotifyPendingInterrupt(PVM pVM, PVMCPU pVCpu, uint8_t u8Interrupt);
+REMR3DECL(uint32_t) REMR3QueryPendingInterrupt(PVM pVM, PVMCPU pVCpu);
+REMR3DECL(void) REMR3NotifyInterruptSet(PVM pVM, PVMCPU pVCpu);
+REMR3DECL(void) REMR3NotifyInterruptClear(PVM pVM, PVMCPU pVCpu);
+REMR3DECL(void) REMR3NotifyTimerPending(PVM pVM, PVMCPU pVCpuDst);
+REMR3DECL(void) REMR3NotifyDmaPending(PVM pVM);
+REMR3DECL(void) REMR3NotifyQueuePending(PVM pVM);
+REMR3DECL(void) REMR3NotifyFF(PVM pVM);
+REMR3DECL(bool) REMR3IsPageAccessHandled(PVM pVM, RTGCPHYS GCPhys);
+/** @} */
+#endif /* IN_RING3 */
+
+
+/** @} */
+RT_C_DECLS_END
+
+
+#endif
+
diff --git a/include/VBox/vmm/selm.h b/include/VBox/vmm/selm.h
new file mode 100644
index 00000000..763d0acf
--- /dev/null
+++ b/include/VBox/vmm/selm.h
@@ -0,0 +1,123 @@
+/** @file
+ * SELM - The Selector Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_selm_h
+#define ___VBox_vmm_selm_h
+
+#include <VBox/types.h>
+#include <iprt/x86.h>
+#include <VBox/dis.h>
+#include <VBox/vmm/dbgfsel.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_selm The Selector Monitor(/Manager) API
+ * @{
+ */
+
+VMMDECL(RTSEL) SELMGetTrap8Selector(PVM pVM);
+VMMDECL(void) SELMSetTrap8EIP(PVM pVM, uint32_t u32EIP);
+VMMDECL(int) SELMGetRing1Stack(PVM pVM, uint32_t *pSS, PRTGCPTR32 pEsp);
+VMMDECL(RTGCPTR) SELMGetGuestTSS(PVM pVM);
+VMMDECL(RTSEL) SELMGetHyperCS(PVM pVM);
+VMMDECL(RTSEL) SELMGetHyperCS64(PVM pVM);
+VMMDECL(RTSEL) SELMGetHyperDS(PVM pVM);
+VMMDECL(RTSEL) SELMGetHyperTSS(PVM pVM);
+VMMDECL(RTSEL) SELMGetHyperTSSTrap08(PVM pVM);
+VMMDECL(RTRCPTR) SELMGetHyperGDT(PVM pVM);
+VMMDECL(int) SELMGetTSSInfo(PVM pVM, PVMCPU pVCpu, PRTGCUINTPTR pGCPtrTss, PRTGCUINTPTR pcbTss, bool *pfCanHaveIOBitmap);
+VMMDECL(RTGCPTR) SELMToFlat(PVM pVM, DISSELREG SelReg, PCPUMCTXCORE pCtxCore, RTGCPTR Addr);
+VMMDECL(RTGCPTR) SELMToFlatBySel(PVM pVM, RTSEL Sel, RTGCPTR Addr);
+VMMDECL(void) SELMShadowCR3Changed(PVM pVM, PVMCPU pVCpu);
+
+/** Flags for SELMToFlatEx().
+ * @{ */
+/** Don't check the RPL,DPL or CPL. */
+#define SELMTOFLAT_FLAGS_NO_PL RT_BIT(8)
+/** Flags contains CPL information. */
+#define SELMTOFLAT_FLAGS_HAVE_CPL RT_BIT(9)
+/** CPL is 3. */
+#define SELMTOFLAT_FLAGS_CPL3 3
+/** CPL is 2. */
+#define SELMTOFLAT_FLAGS_CPL2 2
+/** CPL is 1. */
+#define SELMTOFLAT_FLAGS_CPL1 1
+/** CPL is 0. */
+#define SELMTOFLAT_FLAGS_CPL0 0
+/** Get the CPL from the flags. */
+#define SELMTOFLAT_FLAGS_CPL(fFlags) ((fFlags) & X86_SEL_RPL)
+/** Allow converting using Hypervisor GDT entries. */
+#define SELMTOFLAT_FLAGS_HYPER RT_BIT(10)
+/** @} */
+
+VMMDECL(int) SELMToFlatEx(PVMCPU pVCpu, DISSELREG SelReg, PCPUMCTXCORE pCtxCore, RTGCPTR Addr, uint32_t fFlags,
+ PRTGCPTR ppvGC);
+VMMDECL(int) SELMToFlatBySelEx(PVMCPU pVCpu, X86EFLAGS eflags, RTSEL Sel, RTGCPTR Addr, uint32_t fFlags,
+ PRTGCPTR ppvGC, uint32_t *pcb);
+VMMDECL(int) SELMValidateAndConvertCSAddr(PVMCPU pVCpu, X86EFLAGS eflags, RTSEL SelCPL, RTSEL SelCS,
+ PCPUMSELREG pSRegCS, RTGCPTR Addr, PRTGCPTR ppvFlat);
+#ifdef VBOX_WITH_RAW_MODE
+VMM_INT_DECL(void) SELMLoadHiddenSelectorReg(PVMCPU pVCpu, PCCPUMCTX pCtx, PCPUMSELREG pSReg);
+#endif
+
+
+#ifdef IN_RING3
+/** @defgroup grp_selm_r3 The Selector Monitor(/Manager) API
+ * @ingroup grp_selm
+ * @{
+ */
+VMMR3DECL(int) SELMR3Init(PVM pVM);
+VMMR3DECL(int) SELMR3InitFinalize(PVM pVM);
+VMMR3DECL(void) SELMR3Relocate(PVM pVM);
+VMMR3DECL(int) SELMR3Term(PVM pVM);
+VMMR3DECL(void) SELMR3Reset(PVM pVM);
+VMMR3DECL(VBOXSTRICTRC) SELMR3UpdateFromCPUM(PVM pVM, PVMCPU pVCpu);
+VMMR3DECL(int) SELMR3SyncTSS(PVM pVM, PVMCPU pVCpu);
+VMMR3DECL(int) SELMR3GetSelectorInfo(PVM pVM, PVMCPU pVCpu, RTSEL Sel, PDBGFSELINFO pSelInfo);
+VMMR3DECL(int) SELMR3GetShadowSelectorInfo(PVM pVM, RTSEL Sel, PDBGFSELINFO pSelInfo);
+VMMR3DECL(void) SELMR3DisableMonitoring(PVM pVM);
+VMMR3DECL(void) SELMR3DumpDescriptor(X86DESC Desc, RTSEL Sel, const char *pszMsg);
+VMMR3DECL(void) SELMR3DumpHyperGDT(PVM pVM);
+VMMR3DECL(void) SELMR3DumpHyperLDT(PVM pVM);
+VMMR3DECL(void) SELMR3DumpGuestGDT(PVM pVM);
+VMMR3DECL(void) SELMR3DumpGuestLDT(PVM pVM);
+VMMR3DECL(bool) SELMR3CheckTSS(PVM pVM);
+VMMR3DECL(int) SELMR3DebugCheck(PVM pVM);
+/** @def SELMR3_DEBUG_CHECK
+ * Invokes SELMR3DebugCheck in stricts builds. */
+# ifdef VBOX_STRICT
+# define SELMR3_DEBUG_CHECK(pVM) SELMR3DebugCheck(pVM)
+# else
+# define SELMR3_DEBUG_CHECK(pVM) do { } while (0)
+# endif
+/** @} */
+#endif /* IN_RING3 */
+
+/** @} */
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/ssm.h b/include/VBox/vmm/ssm.h
new file mode 100644
index 00000000..427e0796
--- /dev/null
+++ b/include/VBox/vmm/ssm.h
@@ -0,0 +1,1265 @@
+/** @file
+ * SSM - The Save State Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_ssm_h
+#define ___VBox_vmm_ssm_h
+
+#include <VBox/types.h>
+#include <VBox/vmm/tm.h>
+#include <VBox/vmm/vmapi.h>
+
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_ssm The Saved State Manager API
+ * @{
+ */
+
+/**
+ * Determine the major version of the SSM version. If the major SSM version of two snapshots is
+ * different, the snapshots are incompatible.
+ */
+#define SSM_VERSION_MAJOR(ver) ((ver) & 0xffff0000)
+
+/**
+ * Determine the minor version of the SSM version. If the major SSM version of two snapshots is
+ * the same, the code must handle incompatibilies between minor version changes (e.g. use dummy
+ * values for non-existent fields).
+ */
+#define SSM_VERSION_MINOR(ver) ((ver) & 0x0000ffff)
+
+/**
+ * Determine if the major version changed between two SSM versions.
+ */
+#define SSM_VERSION_MAJOR_CHANGED(ver1,ver2) (SSM_VERSION_MAJOR(ver1) != SSM_VERSION_MAJOR(ver2))
+
+/** The special value for the final pass. */
+#define SSM_PASS_FINAL UINT32_MAX
+
+
+#ifdef IN_RING3
+/** @defgroup grp_ssm_r3 The SSM Host Context Ring-3 API
+ * @{
+ */
+
+
+/**
+ * What to do after the save/load operation.
+ */
+typedef enum SSMAFTER
+{
+ /** Invalid. */
+ SSMAFTER_INVALID = 0,
+ /** Will resume the loaded state. */
+ SSMAFTER_RESUME,
+ /** Will destroy the VM after saving. */
+ SSMAFTER_DESTROY,
+ /** Will continue execution after saving the VM. */
+ SSMAFTER_CONTINUE,
+ /** Will teleport the VM.
+ * The source VM will be destroyed (then one saving), the destination VM
+ * will continue execution. */
+ SSMAFTER_TELEPORT,
+ /** Will debug the saved state.
+ * This is used to drop some of the stricter consitentcy checks so it'll
+ * load fine in the debugger or animator. */
+ SSMAFTER_DEBUG_IT,
+ /** The file was opened using SSMR3Open() and we have no idea what the plan is. */
+ SSMAFTER_OPENED
+} SSMAFTER;
+
+
+/** Pointer to a structure field description. */
+typedef struct SSMFIELD *PSSMFIELD;
+/** Pointer to a const structure field description. */
+typedef const struct SSMFIELD *PCSSMFIELD;
+
+/**
+ * SSMFIELD Get/Put callback function.
+ *
+ * This is call for getting and putting the field it is associated with. It's
+ * up to the callback to work the saved state correctly.
+ *
+ * @returns VBox status code.
+ *
+ * @param pSSM The saved state handle.
+ * @param pField The field that is being processed.
+ * @param pvStruct Pointer to the structure.
+ * @param fFlags SSMSTRUCT_FLAGS_XXX.
+ * @param fGetOrPut True if getting, false if putting.
+ * @param pvUser The user argument specified to SSMR3GetStructEx or
+ * SSMR3PutStructEx.
+ */
+typedef DECLCALLBACK(int) FNSSMFIELDGETPUT(PSSMHANDLE pSSM, const struct SSMFIELD *pField, void *pvStruct,
+ uint32_t fFlags, bool fGetOrPut, void *pvUser);
+/** Pointer to a SSMFIELD Get/Put callback. */
+typedef FNSSMFIELDGETPUT *PFNSSMFIELDGETPUT;
+
+/**
+ * SSM field transformers.
+ *
+ * These are stored in the SSMFIELD::pfnGetPutOrTransformer and must therefore
+ * have values outside the valid pointer range.
+ */
+typedef enum SSMFIELDTRANS
+{
+ /** Invalid. */
+ SSMFIELDTRANS_INVALID = 0,
+ /** No transformation. */
+ SSMFIELDTRANS_NO_TRANSFORMATION,
+ /** Guest context (GC) physical address. */
+ SSMFIELDTRANS_GCPHYS,
+ /** Guest context (GC) virtual address. */
+ SSMFIELDTRANS_GCPTR,
+ /** Raw-mode context (RC) virtual address. */
+ SSMFIELDTRANS_RCPTR,
+ /** Array of raw-mode context (RC) virtual addresses. */
+ SSMFIELDTRANS_RCPTR_ARRAY,
+ /** Host context (HC) virtual address used as a NULL indicator. See
+ * SSMFIELD_ENTRY_HCPTR_NI. */
+ SSMFIELDTRANS_HCPTR_NI,
+ /** Array of SSMFIELDTRANS_HCPTR_NI. */
+ SSMFIELDTRANS_HCPTR_NI_ARRAY,
+ /** Host context (HC) virtual address used to hold a unsigned 32-bit value. */
+ SSMFIELDTRANS_HCPTR_HACK_U32,
+ /** Load a 32-bit unsigned filed from the state and zero extend it into a 64-bit
+ * structure member. */
+ SSMFIELDTRANS_U32_ZX_U64,
+
+ /** Ignorable field. See SSMFIELD_ENTRY_IGNORE. */
+ SSMFIELDTRANS_IGNORE,
+ /** Ignorable guest context (GC) physical address. */
+ SSMFIELDTRANS_IGN_GCPHYS,
+ /** Ignorable guest context (GC) virtual address. */
+ SSMFIELDTRANS_IGN_GCPTR,
+ /** Ignorable raw-mode context (RC) virtual address. */
+ SSMFIELDTRANS_IGN_RCPTR,
+ /** Ignorable host context (HC) virtual address. */
+ SSMFIELDTRANS_IGN_HCPTR,
+
+ /** Old field.
+ * Save as zeros and skip on restore (nowhere to restore it any longer). */
+ SSMFIELDTRANS_OLD,
+ /** Old guest context (GC) physical address. */
+ SSMFIELDTRANS_OLD_GCPHYS,
+ /** Old guest context (GC) virtual address. */
+ SSMFIELDTRANS_OLD_GCPTR,
+ /** Old raw-mode context (RC) virtual address. */
+ SSMFIELDTRANS_OLD_RCPTR,
+ /** Old host context (HC) virtual address. */
+ SSMFIELDTRANS_OLD_HCPTR,
+ /** Old host context specific padding.
+ * The lower word is the size of 32-bit hosts, the upper for 64-bit hosts. */
+ SSMFIELDTRANS_OLD_PAD_HC,
+ /** Old padding specific to the 32-bit Microsoft C Compiler. */
+ SSMFIELDTRANS_OLD_PAD_MSC32,
+
+ /** Padding that differs between 32-bit and 64-bit hosts.
+ * The first byte of SSMFIELD::cb contains the size for 32-bit hosts.
+ * The second byte of SSMFIELD::cb contains the size for 64-bit hosts.
+ * The upper word of SSMFIELD::cb contains the actual field size.
+ */
+ SSMFIELDTRANS_PAD_HC,
+ /** Padding for 32-bit hosts only.
+ * SSMFIELD::cb has the same format as for SSMFIELDTRANS_PAD_HC. */
+ SSMFIELDTRANS_PAD_HC32,
+ /** Padding for 64-bit hosts only.
+ * SSMFIELD::cb has the same format as for SSMFIELDTRANS_PAD_HC. */
+ SSMFIELDTRANS_PAD_HC64,
+ /** Automatic compiler padding that may differ between 32-bit and
+ * 64-bit hosts. SSMFIELD::cb has the same format as for
+ * SSMFIELDTRANS_PAD_HC. */
+ SSMFIELDTRANS_PAD_HC_AUTO,
+ /** Automatic compiler padding specific to the 32-bit Microsoft C
+ * compiler.
+ * SSMFIELD::cb has the same format as for SSMFIELDTRANS_PAD_HC. */
+ SSMFIELDTRANS_PAD_MSC32_AUTO
+} SSMFIELDTRANS;
+
+/** Tests if it's a padding field with the special SSMFIELD::cb format.
+ * @returns true / false.
+ * @param pfn The SSMFIELD::pfnGetPutOrTransformer value.
+ */
+#define SSMFIELDTRANS_IS_PADDING(pfn) \
+ ( (uintptr_t)(pfn) >= SSMFIELDTRANS_PAD_HC && (uintptr_t)(pfn) <= SSMFIELDTRANS_PAD_MSC32_AUTO )
+
+/** Tests if it's an entry for an old field.
+ *
+ * @returns true / false.
+ * @param pfn The SSMFIELD::pfnGetPutOrTransformer value.
+ */
+#define SSMFIELDTRANS_IS_OLD(pfn) \
+ ( (uintptr_t)(pfn) >= SSMFIELDTRANS_OLD && (uintptr_t)(pfn) <= SSMFIELDTRANS_OLD_PAD_MSC32 )
+
+/**
+ * A structure field description.
+ */
+typedef struct SSMFIELD
+{
+ /** Getter and putter callback or transformer index. */
+ PFNSSMFIELDGETPUT pfnGetPutOrTransformer;
+ /** Field offset into the structure. */
+ uint32_t off;
+ /** The size of the field. */
+ uint32_t cb;
+ /** Field name. */
+ const char *pszName;
+} SSMFIELD;
+
+/** Emit a SSMFIELD array entry.
+ * @internal */
+#define SSMFIELD_ENTRY_INT(Name, off, cb, enmTransformer) \
+ { (PFNSSMFIELDGETPUT)(uintptr_t)(enmTransformer), (off), (cb), Name }
+/** Emit a SSMFIELD array entry.
+ * @internal */
+#define SSMFIELD_ENTRY_TF_INT(Type, Field, enmTransformer) \
+ SSMFIELD_ENTRY_INT(#Type "::" #Field, RT_OFFSETOF(Type, Field), RT_SIZEOFMEMB(Type, Field), enmTransformer)
+/** Emit a SSMFIELD array entry for an old field.
+ * @internal */
+#define SSMFIELD_ENTRY_OLD_INT(Field, cb, enmTransformer) \
+ SSMFIELD_ENTRY_INT("old::" #Field, UINT32_MAX / 2, (cb), enmTransformer)
+/** Emit a SSMFIELD array entry for an alignment padding.
+ * @internal */
+#define SSMFIELD_ENTRY_PAD_INT(Type, Field, cb32, cb64, enmTransformer) \
+ SSMFIELD_ENTRY_INT(#Type "::" #Field, RT_OFFSETOF(Type, Field), \
+ (RT_SIZEOFMEMB(Type, Field) << 16) | (cb32) | ((cb64) << 8), enmTransformer)
+/** Emit a SSMFIELD array entry for an alignment padding.
+ * @internal */
+#define SSMFIELD_ENTRY_PAD_OTHER_INT(Type, Field, cb32, cb64, enmTransformer) \
+ SSMFIELD_ENTRY_INT(#Type "::" #Field, UINT32_MAX / 2, 0 | (cb32) | ((cb64) << 8), enmTransformer)
+
+/** Emit a SSMFIELD array entry. */
+#define SSMFIELD_ENTRY(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_NO_TRANSFORMATION)
+/** Emit a SSMFIELD array entry for a custom made field. This is intended
+ * for working around bitfields in old structures. */
+#define SSMFIELD_ENTRY_CUSTOM(Field, off, cb) SSMFIELD_ENTRY_INT("custom::" #Field, off, cb, SSMFIELDTRANS_NO_TRANSFORMATION)
+/** Emit a SSMFIELD array entry for a RTGCPHYS type. */
+#define SSMFIELD_ENTRY_GCPHYS(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_GCPHYS)
+/** Emit a SSMFIELD array entry for a RTGCPTR type. */
+#define SSMFIELD_ENTRY_GCPTR(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_GCPTR)
+/** Emit a SSMFIELD array entry for a raw-mode context pointer. */
+#define SSMFIELD_ENTRY_RCPTR(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_RCPTR)
+/** Emit a SSMFIELD array entry for a raw-mode context pointer. */
+#define SSMFIELD_ENTRY_RCPTR_ARRAY(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_RCPTR_ARRAY)
+/** Emit a SSMFIELD array entry for a ring-0 or ring-3 pointer type that is only
+ * of interest as a NULL indicator.
+ *
+ * This is always restored as a 0 (NULL) or 1 value. When
+ * SSMSTRUCT_FLAGS_DONT_IGNORE is set, the pointer will be saved in its
+ * entirety, when clear it will be saved as a boolean. */
+#define SSMFIELD_ENTRY_HCPTR_NI(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_HCPTR_NI)
+/** Same as SSMFIELD_ENTRY_HCPTR_NI, except it's an array of the buggers. */
+#define SSMFIELD_ENTRY_HCPTR_NI_ARRAY(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_HCPTR_NI_ARRAY)
+/** Emit a SSMFIELD array entry for a ring-0 or ring-3 pointer type that has
+ * been hacked such that it will never exceed 32-bit. No sign extending. */
+#define SSMFIELD_ENTRY_HCPTR_HACK_U32(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_HCPTR_HACK_U32)
+/** Emit a SSMFIELD array entry for loading a 32-bit field into a 64-bit
+ * structure member, zero extending the value. */
+#define SSMFIELD_ENTRY_U32_ZX_U64(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_U32_ZX_U64)
+
+/** Emit a SSMFIELD array entry for a field that can be ignored.
+ * It is stored as zeros if SSMSTRUCT_FLAGS_DONT_IGNORE is specified to
+ * SSMR3PutStructEx. The member is never touched upon restore. */
+#define SSMFIELD_ENTRY_IGNORE(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_IGNORE)
+/** Emit a SSMFIELD array entry for an ignorable RTGCPHYS type. */
+#define SSMFIELD_ENTRY_IGN_GCPHYS(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_IGN_GCPHYS)
+/** Emit a SSMFIELD array entry for an ignorable RTGCPHYS type. */
+#define SSMFIELD_ENTRY_IGN_GCPTR(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_IGN_GCPTR)
+/** Emit a SSMFIELD array entry for an ignorable raw-mode context pointer. */
+#define SSMFIELD_ENTRY_IGN_RCPTR(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_IGN_RCPTR)
+/** Emit a SSMFIELD array entry for an ignorable ring-3 or/and ring-0 pointer. */
+#define SSMFIELD_ENTRY_IGN_HCPTR(Type, Field) SSMFIELD_ENTRY_TF_INT(Type, Field, SSMFIELDTRANS_IGN_HCPTR)
+
+/** Emit a SSMFIELD array entry for an old field that should be ignored now.
+ * It is stored as zeros and skipped on load. */
+#define SSMFIELD_ENTRY_OLD(Field, cb) SSMFIELD_ENTRY_OLD_INT(Field, cb, SSMFIELDTRANS_OLD)
+/** Same as SSMFIELD_ENTRY_IGN_GCPHYS, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_GCPHYS(Field) SSMFIELD_ENTRY_OLD_INT(Field, sizeof(RTGCPHYS), SSMFIELDTRANS_OLD_GCPHYS)
+/** Same as SSMFIELD_ENTRY_IGN_GCPTR, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_GCPTR(Field) SSMFIELD_ENTRY_OLD_INT(Field, sizeof(RTGCPTR), SSMFIELDTRANS_OLD_GCPTR)
+/** Same as SSMFIELD_ENTRY_IGN_RCPTR, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_RCPTR(Field) SSMFIELD_ENTRY_OLD_INT(Field, sizeof(RTRCPTR), SSMFIELDTRANS_OLD_RCPTR)
+/** Same as SSMFIELD_ENTRY_IGN_HCPTR, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_HCPTR(Field) SSMFIELD_ENTRY_OLD_INT(Field, sizeof(RTHCPTR), SSMFIELDTRANS_OLD_HCPTR)
+/** Same as SSMFIELD_ENTRY_PAD_HC, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_PAD_HC(Field, cb32, cb64) \
+ SSMFIELD_ENTRY_OLD_INT(Field, RT_MAKE_U32((cb32), (cb64)), SSMFIELDTRANS_OLD_PAD_HC)
+/** Same as SSMFIELD_ENTRY_PAD_HC64, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_PAD_HC64(Field, cb) SSMFIELD_ENTRY_OLD_PAD_HC(Field, 0, cb)
+/** Same as SSMFIELD_ENTRY_PAD_HC32, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_PAD_HC32(Field, cb) SSMFIELD_ENTRY_OLD_PAD_HC(Field, cb, 0)
+/** Same as SSMFIELD_ENTRY_PAD_HC, except there is no structure field. */
+#define SSMFIELD_ENTRY_OLD_PAD_MSC32(Field, cb) SSMFIELD_ENTRY_OLD_INT(Field, cb, SSMFIELDTRANS_OLD_PAD_MSC32)
+
+/** Emit a SSMFIELD array entry for a padding that differs in size between
+ * 64-bit and 32-bit hosts. */
+#define SSMFIELD_ENTRY_PAD_HC(Type, Field, cb32, cb64) SSMFIELD_ENTRY_PAD_INT( Type, Field, cb32, cb64, SSMFIELDTRANS_PAD_HC)
+/** Emit a SSMFIELD array entry for a padding that is exclusive to 64-bit hosts. */
+#if HC_ARCH_BITS == 64
+# define SSMFIELD_ENTRY_PAD_HC64(Type, Field, cb) SSMFIELD_ENTRY_PAD_INT( Type, Field, 0, cb, SSMFIELDTRANS_PAD_HC64)
+#else
+# define SSMFIELD_ENTRY_PAD_HC64(Type, Field, cb) SSMFIELD_ENTRY_PAD_OTHER_INT(Type, Field, 0, cb, SSMFIELDTRANS_PAD_HC64)
+#endif
+/** Emit a SSMFIELD array entry for a 32-bit padding for on 64-bits hosts. */
+#if HC_ARCH_BITS == 32
+# define SSMFIELD_ENTRY_PAD_HC32(Type, Field, cb) SSMFIELD_ENTRY_PAD_INT( Type, Field, cb, 0, SSMFIELDTRANS_PAD_HC32)
+#else
+# define SSMFIELD_ENTRY_PAD_HC32(Type, Field, cb) SSMFIELD_ENTRY_PAD_OTHER_INT(Type, Field, cb, 0, SSMFIELDTRANS_PAD_HC32)
+#endif
+/** Emit a SSMFIELD array entry for an automatic compiler padding that may
+ * differ in size between 64-bit and 32-bit hosts. */
+#if HC_ARCH_BITS == 64
+# define SSMFIELD_ENTRY_PAD_HC_AUTO(cb32, cb64) \
+ { \
+ (PFNSSMFIELDGETPUT)(uintptr_t)(SSMFIELDTRANS_PAD_HC_AUTO), \
+ UINT32_MAX / 2, (cb64 << 16) | (cb32) | ((cb64) << 8), "<compiler-padding>" \
+ }
+#else
+# define SSMFIELD_ENTRY_PAD_HC_AUTO(cb32, cb64) \
+ { \
+ (PFNSSMFIELDGETPUT)(uintptr_t)(SSMFIELDTRANS_PAD_HC_AUTO), \
+ UINT32_MAX / 2, (cb32 << 16) | (cb32) | ((cb64) << 8), "<compiler-padding>" \
+ }
+#endif
+/** Emit a SSMFIELD array entry for an automatic compiler padding that is unique
+ * to the 32-bit microsoft compiler. This is usually used together with
+ * SSMFIELD_ENTRY_PAD_HC*. */
+#if HC_ARCH_BITS == 32 && defined(_MSC_VER)
+# define SSMFIELD_ENTRY_PAD_MSC32_AUTO(cb) \
+ { \
+ (PFNSSMFIELDGETPUT)(uintptr_t)(SSMFIELDTRANS_PAD_MSC32_AUTO), \
+ UINT32_MAX / 2, ((cb) << 16) | (cb), "<msc32-padding>" \
+ }
+#else
+# define SSMFIELD_ENTRY_PAD_MSC32_AUTO(cb) \
+ { \
+ (PFNSSMFIELDGETPUT)(uintptr_t)(SSMFIELDTRANS_PAD_MSC32_AUTO), \
+ UINT32_MAX / 2, (cb), "<msc32-padding>" \
+ }
+#endif
+
+/** Emit a SSMFIELD array entry for a field with a custom callback. */
+#define SSMFIELD_ENTRY_CALLBACK(Type, Field, pfnGetPut) \
+ { (pfnGetPut), RT_OFFSETOF(Type, Field), RT_SIZEOFMEMB(Type, Field), #Type "::" #Field }
+/** Emit the terminating entry of a SSMFIELD array. */
+#define SSMFIELD_ENTRY_TERM() { (PFNSSMFIELDGETPUT)(uintptr_t)SSMFIELDTRANS_INVALID, UINT32_MAX, UINT32_MAX, NULL }
+
+
+/** @name SSMR3GetStructEx and SSMR3PutStructEx flags.
+ * @{ */
+/** The field descriptors must exactly cover the entire struct, A to Z. */
+#define SSMSTRUCT_FLAGS_FULL_STRUCT RT_BIT_32(0)
+/** No start and end markers, just the raw bits. */
+#define SSMSTRUCT_FLAGS_NO_MARKERS RT_BIT_32(1)
+/** Do not ignore any ignorable fields. */
+#define SSMSTRUCT_FLAGS_DONT_IGNORE RT_BIT_32(2)
+/** Saved using SSMR3PutMem, don't be too strict. */
+#define SSMSTRUCT_FLAGS_SAVED_AS_MEM RT_BIT_32(3)
+/** Band-aid for old SSMR3PutMem/SSMR3GetMem of structurs with host pointers. */
+#define SSMSTRUCT_FLAGS_MEM_BAND_AID ( SSMSTRUCT_FLAGS_DONT_IGNORE | SSMSTRUCT_FLAGS_FULL_STRUCT \
+ | SSMSTRUCT_FLAGS_NO_MARKERS | SSMSTRUCT_FLAGS_SAVED_AS_MEM)
+/** Band-aid for old SSMR3PutMem/SSMR3GetMem of structurs with host
+ * pointers, with relaxed checks. */
+#define SSMSTRUCT_FLAGS_MEM_BAND_AID_RELAXED ( SSMSTRUCT_FLAGS_DONT_IGNORE \
+ | SSMSTRUCT_FLAGS_NO_MARKERS | SSMSTRUCT_FLAGS_SAVED_AS_MEM)
+/** Mask of the valid bits. */
+#define SSMSTRUCT_FLAGS_VALID_MASK UINT32_C(0x0000000f)
+/** @} */
+
+
+/** The PDM Device callback variants.
+ * @{
+ */
+
+/**
+ * Prepare state live save operation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @thread Any.
+ */
+typedef DECLCALLBACK(int) FNSSMDEVLIVEPREP(PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMDEVLIVEPREP() function. */
+typedef FNSSMDEVLIVEPREP *PFNSSMDEVLIVEPREP;
+
+/**
+ * Execute state live save operation.
+ *
+ * This will be called repeatedly until all units vote that the live phase has
+ * been concluded.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @param uPass The pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACK(int) FNSSMDEVLIVEEXEC(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass);
+/** Pointer to a FNSSMDEVLIVEEXEC() function. */
+typedef FNSSMDEVLIVEEXEC *PFNSSMDEVLIVEEXEC;
+
+/**
+ * Vote on whether the live part of the saving has been concluded.
+ *
+ * The vote stops once a unit has vetoed the decision, so don't rely upon this
+ * being called every time.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS if done.
+ * @retval VINF_SSM_VOTE_FOR_ANOTHER_PASS if another pass is needed.
+ * @retval VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN if the live saving of the unit is
+ * done and there is not need calling it again before the final pass.
+ * @retval VERR_SSM_VOTE_FOR_GIVING_UP if its time to give up.
+ *
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @param uPass The data pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACK(int) FNSSMDEVLIVEVOTE(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uPass);
+/** Pointer to a FNSSMDEVLIVEVOTE() function. */
+typedef FNSSMDEVLIVEVOTE *PFNSSMDEVLIVEVOTE;
+
+/**
+ * Prepare state save operation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMDEVSAVEPREP(PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMDEVSAVEPREP() function. */
+typedef FNSSMDEVSAVEPREP *PFNSSMDEVSAVEPREP;
+
+/**
+ * Execute state save operation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMDEVSAVEEXEC(PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMDEVSAVEEXEC() function. */
+typedef FNSSMDEVSAVEEXEC *PFNSSMDEVSAVEEXEC;
+
+/**
+ * Done state save operation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMDEVSAVEDONE(PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMDEVSAVEDONE() function. */
+typedef FNSSMDEVSAVEDONE *PFNSSMDEVSAVEDONE;
+
+/**
+ * Prepare state load operation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMDEVLOADPREP(PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMDEVLOADPREP() function. */
+typedef FNSSMDEVLOADPREP *PFNSSMDEVLOADPREP;
+
+/**
+ * Execute state load operation.
+ *
+ * @returns VBox status code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @param uVersion Data layout version.
+ * @param uPass The pass. This is always SSM_PASS_FINAL for units
+ * that doesn't specify a pfnSaveLive callback.
+ */
+typedef DECLCALLBACK(int) FNSSMDEVLOADEXEC(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
+/** Pointer to a FNSSMDEVLOADEXEC() function. */
+typedef FNSSMDEVLOADEXEC *PFNSSMDEVLOADEXEC;
+
+/**
+ * Done state load operation.
+ *
+ * @returns VBox load code.
+ * @param pDevIns Device instance of the device which registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMDEVLOADDONE(PPDMDEVINS pDevIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMDEVLOADDONE() function. */
+typedef FNSSMDEVLOADDONE *PFNSSMDEVLOADDONE;
+
+/** @} */
+
+
+/** The PDM USB device callback variants.
+ * @{
+ */
+
+/**
+ * Prepare state live save operation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @thread Any.
+ */
+typedef DECLCALLBACK(int) FNSSMUSBLIVEPREP(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMUSBLIVEPREP() function. */
+typedef FNSSMUSBLIVEPREP *PFNSSMUSBLIVEPREP;
+
+/**
+ * Execute state live save operation.
+ *
+ * This will be called repeatedly until all units vote that the live phase has
+ * been concluded.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @param uPass The pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACK(int) FNSSMUSBLIVEEXEC(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM, uint32_t uPass);
+/** Pointer to a FNSSMUSBLIVEEXEC() function. */
+typedef FNSSMUSBLIVEEXEC *PFNSSMUSBLIVEEXEC;
+
+/**
+ * Vote on whether the live part of the saving has been concluded.
+ *
+ * The vote stops once a unit has vetoed the decision, so don't rely upon this
+ * being called every time.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS if done.
+ * @retval VINF_SSM_VOTE_FOR_ANOTHER_PASS if another pass is needed.
+ * @retval VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN if the live saving of the unit is
+ * done and there is not need calling it again before the final pass.
+ * @retval VERR_SSM_VOTE_FOR_GIVING_UP if its time to give up.
+ *
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @param uPass The data pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACK(int) FNSSMUSBLIVEVOTE(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM, uint32_t uPass);
+/** Pointer to a FNSSMUSBLIVEVOTE() function. */
+typedef FNSSMUSBLIVEVOTE *PFNSSMUSBLIVEVOTE;
+
+/**
+ * Prepare state save operation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMUSBSAVEPREP(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMUSBSAVEPREP() function. */
+typedef FNSSMUSBSAVEPREP *PFNSSMUSBSAVEPREP;
+
+/**
+ * Execute state save operation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMUSBSAVEEXEC(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMUSBSAVEEXEC() function. */
+typedef FNSSMUSBSAVEEXEC *PFNSSMUSBSAVEEXEC;
+
+/**
+ * Done state save operation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMUSBSAVEDONE(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMUSBSAVEDONE() function. */
+typedef FNSSMUSBSAVEDONE *PFNSSMUSBSAVEDONE;
+
+/**
+ * Prepare state load operation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMUSBLOADPREP(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMUSBLOADPREP() function. */
+typedef FNSSMUSBLOADPREP *PFNSSMUSBLOADPREP;
+
+/**
+ * Execute state load operation.
+ *
+ * @returns VBox status code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @param uVersion Data layout version.
+ * @param uPass The pass. This is always SSM_PASS_FINAL for units
+ * that doesn't specify a pfnSaveLive callback.
+ */
+typedef DECLCALLBACK(int) FNSSMUSBLOADEXEC(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
+/** Pointer to a FNSSMUSBLOADEXEC() function. */
+typedef FNSSMUSBLOADEXEC *PFNSSMUSBLOADEXEC;
+
+/**
+ * Done state load operation.
+ *
+ * @returns VBox load code.
+ * @param pUsbIns The USB device instance of the USB device which
+ * registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMUSBLOADDONE(PPDMUSBINS pUsbIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMUSBLOADDONE() function. */
+typedef FNSSMUSBLOADDONE *PFNSSMUSBLOADDONE;
+
+/** @} */
+
+
+/** The PDM Driver callback variants.
+ * @{
+ */
+
+/**
+ * Prepare state live save operation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance of the driver which registered the
+ * data unit.
+ * @param pSSM SSM operation handle.
+ * @thread Any.
+ */
+typedef DECLCALLBACK(int) FNSSMDRVLIVEPREP(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMDRVLIVEPREP() function. */
+typedef FNSSMDRVLIVEPREP *PFNSSMDRVLIVEPREP;
+
+/**
+ * Execute state live save operation.
+ *
+ * This will be called repeatedly until all units vote that the live phase has
+ * been concluded.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance of the driver which registered the
+ * data unit.
+ * @param pSSM SSM operation handle.
+ * @param uPass The data pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACK(int) FNSSMDRVLIVEEXEC(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM, uint32_t uPass);
+/** Pointer to a FNSSMDRVLIVEEXEC() function. */
+typedef FNSSMDRVLIVEEXEC *PFNSSMDRVLIVEEXEC;
+
+/**
+ * Vote on whether the live part of the saving has been concluded.
+ *
+ * The vote stops once a unit has vetoed the decision, so don't rely upon this
+ * being called every time.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS if done.
+ * @retval VINF_SSM_VOTE_FOR_ANOTHER_PASS if another pass is needed.
+ * @retval VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN if the live saving of the unit is
+ * done and there is not need calling it again before the final pass.
+ * @retval VERR_SSM_VOTE_FOR_GIVING_UP if its time to give up.
+ *
+ * @param pDrvIns Driver instance of the driver which registered the
+ * data unit.
+ * @param pSSM SSM operation handle.
+ * @param uPass The data pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACK(int) FNSSMDRVLIVEVOTE(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM, uint32_t uPass);
+/** Pointer to a FNSSMDRVLIVEVOTE() function. */
+typedef FNSSMDRVLIVEVOTE *PFNSSMDRVLIVEVOTE;
+
+
+/**
+ * Prepare state save operation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance of the driver which registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMDRVSAVEPREP(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMDRVSAVEPREP() function. */
+typedef FNSSMDRVSAVEPREP *PFNSSMDRVSAVEPREP;
+
+/**
+ * Execute state save operation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance of the driver which registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMDRVSAVEEXEC(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMDRVSAVEEXEC() function. */
+typedef FNSSMDRVSAVEEXEC *PFNSSMDRVSAVEEXEC;
+
+/**
+ * Done state save operation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance of the driver which registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMDRVSAVEDONE(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMDRVSAVEDONE() function. */
+typedef FNSSMDRVSAVEDONE *PFNSSMDRVSAVEDONE;
+
+/**
+ * Prepare state load operation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance of the driver which registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMDRVLOADPREP(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMDRVLOADPREP() function. */
+typedef FNSSMDRVLOADPREP *PFNSSMDRVLOADPREP;
+
+/**
+ * Execute state load operation.
+ *
+ * @returns VBox status code.
+ * @param pDrvIns Driver instance of the driver which registered the data unit.
+ * @param pSSM SSM operation handle.
+ * @param uVersion Data layout version.
+ * @param uPass The pass. This is always SSM_PASS_FINAL for units
+ * that doesn't specify a pfnSaveLive callback.
+ */
+typedef DECLCALLBACK(int) FNSSMDRVLOADEXEC(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
+/** Pointer to a FNSSMDRVLOADEXEC() function. */
+typedef FNSSMDRVLOADEXEC *PFNSSMDRVLOADEXEC;
+
+/**
+ * Done state load operation.
+ *
+ * @returns VBox load code.
+ * @param pDrvIns Driver instance of the driver which registered the data unit.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMDRVLOADDONE(PPDMDRVINS pDrvIns, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMDRVLOADDONE() function. */
+typedef FNSSMDRVLOADDONE *PFNSSMDRVLOADDONE;
+
+/** @} */
+
+
+/** The internal callback variants.
+ * @{
+ */
+
+
+/**
+ * Prepare state live save operation.
+ *
+ * @returns VBox status code.
+ * @param pVM VM Handle.
+ * @param pSSM SSM operation handle.
+ * @thread Any.
+ */
+typedef DECLCALLBACK(int) FNSSMINTLIVEPREP(PVM pVM, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMINTLIVEPREP() function. */
+typedef FNSSMINTLIVEPREP *PFNSSMINTLIVEPREP;
+
+/**
+ * Execute state live save operation.
+ *
+ * This will be called repeatedly until all units vote that the live phase has
+ * been concluded.
+ *
+ * @returns VBox status code.
+ * @param pVM VM Handle.
+ * @param pSSM SSM operation handle.
+ * @param uPass The data pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACK(int) FNSSMINTLIVEEXEC(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass);
+/** Pointer to a FNSSMINTLIVEEXEC() function. */
+typedef FNSSMINTLIVEEXEC *PFNSSMINTLIVEEXEC;
+
+/**
+ * Vote on whether the live part of the saving has been concluded.
+ *
+ * The vote stops once a unit has vetoed the decision, so don't rely upon this
+ * being called every time.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS if done.
+ * @retval VINF_SSM_VOTE_FOR_ANOTHER_PASS if another pass is needed.
+ * @retval VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN if the live saving of the unit is
+ * done and there is not need calling it again before the final pass.
+ * @retval VERR_SSM_VOTE_FOR_GIVING_UP if its time to give up.
+ *
+ * @param pVM VM Handle.
+ * @param pSSM SSM operation handle.
+ * @param uPass The data pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACK(int) FNSSMINTLIVEVOTE(PVM pVM, PSSMHANDLE pSSM, uint32_t uPass);
+/** Pointer to a FNSSMINTLIVEVOTE() function. */
+typedef FNSSMINTLIVEVOTE *PFNSSMINTLIVEVOTE;
+
+/**
+ * Prepare state save operation.
+ *
+ * @returns VBox status code.
+ * @param pVM VM Handle.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMINTSAVEPREP(PVM pVM, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMINTSAVEPREP() function. */
+typedef FNSSMINTSAVEPREP *PFNSSMINTSAVEPREP;
+
+/**
+ * Execute state save operation.
+ *
+ * @returns VBox status code.
+ * @param pVM VM Handle.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMINTSAVEEXEC(PVM pVM, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMINTSAVEEXEC() function. */
+typedef FNSSMINTSAVEEXEC *PFNSSMINTSAVEEXEC;
+
+/**
+ * Done state save operation.
+ *
+ * @returns VBox status code.
+ * @param pVM VM Handle.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMINTSAVEDONE(PVM pVM, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMINTSAVEDONE() function. */
+typedef FNSSMINTSAVEDONE *PFNSSMINTSAVEDONE;
+
+/**
+ * Prepare state load operation.
+ *
+ * @returns VBox status code.
+ * @param pVM VM Handle.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMINTLOADPREP(PVM pVM, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMINTLOADPREP() function. */
+typedef FNSSMINTLOADPREP *PFNSSMINTLOADPREP;
+
+/**
+ * Execute state load operation.
+ *
+ * @returns VBox status code.
+ * @param pVM VM Handle.
+ * @param pSSM SSM operation handle.
+ * @param uVersion Data layout version.
+ * @param uPass The pass. This is always SSM_PASS_FINAL for units
+ * that doesn't specify a pfnSaveLive callback.
+ */
+typedef DECLCALLBACK(int) FNSSMINTLOADEXEC(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass);
+/** Pointer to a FNSSMINTLOADEXEC() function. */
+typedef FNSSMINTLOADEXEC *PFNSSMINTLOADEXEC;
+
+/**
+ * Done state load operation.
+ *
+ * @returns VBox load code.
+ * @param pVM VM Handle.
+ * @param pSSM SSM operation handle.
+ */
+typedef DECLCALLBACK(int) FNSSMINTLOADDONE(PVM pVM, PSSMHANDLE pSSM);
+/** Pointer to a FNSSMINTLOADDONE() function. */
+typedef FNSSMINTLOADDONE *PFNSSMINTLOADDONE;
+
+/** @} */
+
+
+/** The External callback variants.
+ * @{
+ */
+
+/**
+ * Prepare state live save operation.
+ *
+ * @returns VBox status code.
+ * @param pSSM SSM operation handle.
+ * @param pvUser User argument.
+ * @thread Any.
+ */
+typedef DECLCALLBACK(int) FNSSMEXTLIVEPREP(PSSMHANDLE pSSM, void *pvUser);
+/** Pointer to a FNSSMEXTLIVEPREP() function. */
+typedef FNSSMEXTLIVEPREP *PFNSSMEXTLIVEPREP;
+
+/**
+ * Execute state live save operation.
+ *
+ * This will be called repeatedly until all units vote that the live phase has
+ * been concluded.
+ *
+ * @returns VBox status code.
+ * @param pSSM SSM operation handle.
+ * @param pvUser User argument.
+ * @param uPass The data pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACK(int) FNSSMEXTLIVEEXEC(PSSMHANDLE pSSM, void *pvUser, uint32_t uPass);
+/** Pointer to a FNSSMEXTLIVEEXEC() function. */
+typedef FNSSMEXTLIVEEXEC *PFNSSMEXTLIVEEXEC;
+
+/**
+ * Vote on whether the live part of the saving has been concluded.
+ *
+ * The vote stops once a unit has vetoed the decision, so don't rely upon this
+ * being called every time.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS if done.
+ * @retval VINF_SSM_VOTE_FOR_ANOTHER_PASS if another pass is needed.
+ * @retval VINF_SSM_VOTE_DONE_DONT_CALL_AGAIN if the live saving of the unit is
+ * done and there is not need calling it again before the final pass.
+ * @retval VERR_SSM_VOTE_FOR_GIVING_UP if its time to give up.
+ *
+ * @param pSSM SSM operation handle.
+ * @param pvUser User argument.
+ * @param uPass The data pass.
+ * @thread Any.
+ */
+typedef DECLCALLBACK(int) FNSSMEXTLIVEVOTE(PSSMHANDLE pSSM, void *pvUser, uint32_t uPass);
+/** Pointer to a FNSSMEXTLIVEVOTE() function. */
+typedef FNSSMEXTLIVEVOTE *PFNSSMEXTLIVEVOTE;
+
+/**
+ * Prepare state save operation.
+ *
+ * @returns VBox status code.
+ * @param pSSM SSM operation handle.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACK(int) FNSSMEXTSAVEPREP(PSSMHANDLE pSSM, void *pvUser);
+/** Pointer to a FNSSMEXTSAVEPREP() function. */
+typedef FNSSMEXTSAVEPREP *PFNSSMEXTSAVEPREP;
+
+/**
+ * Execute state save operation.
+ *
+ * @param pSSM SSM operation handle.
+ * @param pvUser User argument.
+ * @author The lack of return code is for legacy reasons.
+ */
+typedef DECLCALLBACK(void) FNSSMEXTSAVEEXEC(PSSMHANDLE pSSM, void *pvUser);
+/** Pointer to a FNSSMEXTSAVEEXEC() function. */
+typedef FNSSMEXTSAVEEXEC *PFNSSMEXTSAVEEXEC;
+
+/**
+ * Done state save operation.
+ *
+ * @returns VBox status code.
+ * @param pSSM SSM operation handle.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACK(int) FNSSMEXTSAVEDONE(PSSMHANDLE pSSM, void *pvUser);
+/** Pointer to a FNSSMEXTSAVEDONE() function. */
+typedef FNSSMEXTSAVEDONE *PFNSSMEXTSAVEDONE;
+
+/**
+ * Prepare state load operation.
+ *
+ * @returns VBox status code.
+ * @param pSSM SSM operation handle.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACK(int) FNSSMEXTLOADPREP(PSSMHANDLE pSSM, void *pvUser);
+/** Pointer to a FNSSMEXTLOADPREP() function. */
+typedef FNSSMEXTLOADPREP *PFNSSMEXTLOADPREP;
+
+/**
+ * Execute state load operation.
+ *
+ * @returns VBox status code.
+ * @param pSSM SSM operation handle.
+ * @param pvUser User argument.
+ * @param uVersion Data layout version.
+ * @param uPass The pass. This is always SSM_PASS_FINAL for units
+ * that doesn't specify a pfnSaveLive callback.
+ * @remark The odd return value is for legacy reasons.
+ */
+typedef DECLCALLBACK(int) FNSSMEXTLOADEXEC(PSSMHANDLE pSSM, void *pvUser, uint32_t uVersion, uint32_t uPass);
+/** Pointer to a FNSSMEXTLOADEXEC() function. */
+typedef FNSSMEXTLOADEXEC *PFNSSMEXTLOADEXEC;
+
+/**
+ * Done state load operation.
+ *
+ * @returns VBox load code.
+ * @param pSSM SSM operation handle.
+ * @param pvUser User argument.
+ */
+typedef DECLCALLBACK(int) FNSSMEXTLOADDONE(PSSMHANDLE pSSM, void *pvUser);
+/** Pointer to a FNSSMEXTLOADDONE() function. */
+typedef FNSSMEXTLOADDONE *PFNSSMEXTLOADDONE;
+
+/** @} */
+
+
+/**
+ * SSM stream method table.
+ *
+ * This is used by external parties for teleporting over TCP or any other media.
+ * SSM also uses this internally for file access, thus the 2-3 file centric
+ * methods.
+ */
+typedef struct SSMSTRMOPS
+{
+ /** Struct magic + version (SSMSTRMOPS_VERSION). */
+ uint32_t u32Version;
+
+ /**
+ * Write bytes to the stream.
+ *
+ * @returns VBox status code.
+ * @param pvUser The user argument.
+ * @param offStream The stream offset we're (supposed to be) at.
+ * @param pvBuf Pointer to the data.
+ * @param cbToWrite The number of bytes to write.
+ */
+ DECLCALLBACKMEMBER(int, pfnWrite)(void *pvUser, uint64_t offStream, const void *pvBuf, size_t cbToWrite);
+
+ /**
+ * Read bytes to the stream.
+ *
+ * @returns VBox status code.
+ * @param pvUser The user argument.
+ * @param offStream The stream offset we're (supposed to be) at.
+ * @param pvBuf Where to return the bytes.
+ * @param cbToRead The number of bytes to read.
+ * @param pcbRead Where to return the number of bytes actually
+ * read. This may differ from cbToRead when the
+ * end of the stream is encountered.
+ */
+ DECLCALLBACKMEMBER(int, pfnRead)(void *pvUser, uint64_t offStream, void *pvBuf, size_t cbToRead, size_t *pcbRead);
+
+ /**
+ * Seeks in the stream.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_SUPPORTED if the stream doesn't support this action.
+ *
+ * @param pvUser The user argument.
+ * @param offSeek The seek offset.
+ * @param uMethod RTFILE_SEEK_BEGIN, RTFILE_SEEK_END or
+ * RTFILE_SEEK_CURRENT.
+ * @param poffActual Where to store the new file position. Optional.
+ */
+ DECLCALLBACKMEMBER(int, pfnSeek)(void *pvUser, int64_t offSeek, unsigned uMethod, uint64_t *poffActual);
+
+ /**
+ * Get the current stream position.
+ *
+ * @returns The correct stream position.
+ * @param pvUser The user argument.
+ */
+ DECLCALLBACKMEMBER(uint64_t, pfnTell)(void *pvUser);
+
+ /**
+ * Get the size/length of the stream.
+ *
+ * @returns VBox status code.
+ * @retval VERR_NOT_SUPPORTED if the stream doesn't support this action.
+ *
+ * @param pvUser The user argument.
+ * @param pcb Where to return the size/length.
+ */
+ DECLCALLBACKMEMBER(int, pfnSize)(void *pvUser, uint64_t *pcb);
+
+ /**
+ * Check if the stream is OK or not (cancelled).
+ *
+ * @returns VBox status code.
+ * @param pvUser The user argument.
+ *
+ * @remarks The method is expected to do a LogRel on failure.
+ */
+ DECLCALLBACKMEMBER(int, pfnIsOk)(void *pvUser);
+
+ /**
+ * Close the stream.
+ *
+ * @returns VBox status code.
+ * @param pvUser The user argument.
+ * @param fCancelled True if the operation was cancelled.
+ */
+ DECLCALLBACKMEMBER(int, pfnClose)(void *pvUser, bool fCancelled);
+
+ /** Struct magic + version (SSMSTRMOPS_VERSION). */
+ uint32_t u32EndVersion;
+} SSMSTRMOPS;
+/** Struct magic + version (SSMSTRMOPS_VERSION). */
+#define SSMSTRMOPS_VERSION UINT32_C(0x55aa0001)
+
+
+VMMR3_INT_DECL(void) SSMR3Term(PVM pVM);
+VMMR3DECL(int) SSMR3RegisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess, const char *pszBefore,
+ PFNSSMDEVLIVEPREP pfnLivePrep, PFNSSMDEVLIVEEXEC pfnLiveExec, PFNSSMDEVLIVEVOTE pfnLiveVote,
+ PFNSSMDEVSAVEPREP pfnSavePrep, PFNSSMDEVSAVEEXEC pfnSaveExec, PFNSSMDEVSAVEDONE pfnSaveDone,
+ PFNSSMDEVLOADPREP pfnLoadPrep, PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone);
+VMMR3DECL(int) SSMR3RegisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess,
+ PFNSSMDRVLIVEPREP pfnLivePrep, PFNSSMDRVLIVEEXEC pfnLiveExec, PFNSSMDRVLIVEVOTE pfnLiveVote,
+ PFNSSMDRVSAVEPREP pfnSavePrep, PFNSSMDRVSAVEEXEC pfnSaveExec, PFNSSMDRVSAVEDONE pfnSaveDone,
+ PFNSSMDRVLOADPREP pfnLoadPrep, PFNSSMDRVLOADEXEC pfnLoadExec, PFNSSMDRVLOADDONE pfnLoadDone);
+VMMR3DECL(int) SSMR3RegisterInternal(PVM pVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess,
+ PFNSSMINTLIVEPREP pfnLivePrep, PFNSSMINTLIVEEXEC pfnLiveExec, PFNSSMINTLIVEVOTE pfnLiveVote,
+ PFNSSMINTSAVEPREP pfnSavePrep, PFNSSMINTSAVEEXEC pfnSaveExec, PFNSSMINTSAVEDONE pfnSaveDone,
+ PFNSSMINTLOADPREP pfnLoadPrep, PFNSSMINTLOADEXEC pfnLoadExec, PFNSSMINTLOADDONE pfnLoadDone);
+VMMR3DECL(int) SSMR3RegisterExternal(PVM pVM, const char *pszName, uint32_t uInstance, uint32_t uVersion, size_t cbGuess,
+ PFNSSMEXTLIVEPREP pfnLivePrep, PFNSSMEXTLIVEEXEC pfnLiveExec, PFNSSMEXTLIVEVOTE pfnLiveVote,
+ PFNSSMEXTSAVEPREP pfnSavePrep, PFNSSMEXTSAVEEXEC pfnSaveExec, PFNSSMEXTSAVEDONE pfnSaveDone,
+ PFNSSMEXTLOADPREP pfnLoadPrep, PFNSSMEXTLOADEXEC pfnLoadExec, PFNSSMEXTLOADDONE pfnLoadDone, void *pvUser);
+VMMR3_INT_DECL(int) SSMR3DeregisterDevice(PVM pVM, PPDMDEVINS pDevIns, const char *pszName, uint32_t uInstance);
+VMMR3_INT_DECL(int) SSMR3DeregisterDriver(PVM pVM, PPDMDRVINS pDrvIns, const char *pszName, uint32_t uInstance);
+VMMR3DECL(int) SSMR3DeregisterInternal(PVM pVM, const char *pszName);
+VMMR3DECL(int) SSMR3DeregisterExternal(PVM pVM, const char *pszName);
+VMMR3DECL(int) SSMR3Save(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvUser);
+VMMR3_INT_DECL(int) SSMR3LiveSave(PVM pVM, uint32_t cMsMaxDowntime,
+ const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOps,
+ SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser,
+ PSSMHANDLE *ppSSM);
+VMMR3_INT_DECL(int) SSMR3LiveDoStep1(PSSMHANDLE pSSM);
+VMMR3_INT_DECL(int) SSMR3LiveDoStep2(PSSMHANDLE pSSM);
+VMMR3_INT_DECL(int) SSMR3LiveDone(PSSMHANDLE pSSM);
+VMMR3DECL(int) SSMR3Load(PVM pVM, const char *pszFilename, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
+ SSMAFTER enmAfter, PFNVMPROGRESS pfnProgress, void *pvProgressUser);
+VMMR3DECL(int) SSMR3ValidateFile(const char *pszFilename, bool fChecksumIt);
+VMMR3DECL(int) SSMR3Open(const char *pszFilename, unsigned fFlags, PSSMHANDLE *ppSSM);
+VMMR3DECL(int) SSMR3Close(PSSMHANDLE pSSM);
+VMMR3DECL(int) SSMR3Seek(PSSMHANDLE pSSM, const char *pszUnit, uint32_t iInstance, uint32_t *piVersion);
+VMMR3DECL(int) SSMR3HandleGetStatus(PSSMHANDLE pSSM);
+VMMR3DECL(int) SSMR3HandleSetStatus(PSSMHANDLE pSSM, int iStatus);
+VMMR3DECL(SSMAFTER) SSMR3HandleGetAfter(PSSMHANDLE pSSM);
+VMMR3DECL(bool) SSMR3HandleIsLiveSave(PSSMHANDLE pSSM);
+VMMR3DECL(uint32_t) SSMR3HandleMaxDowntime(PSSMHANDLE pSSM);
+VMMR3DECL(uint32_t) SSMR3HandleHostBits(PSSMHANDLE pSSM);
+VMMR3DECL(uint32_t) SSMR3HandleRevision(PSSMHANDLE pSSM);
+VMMR3DECL(uint32_t) SSMR3HandleVersion(PSSMHANDLE pSSM);
+VMMR3DECL(const char *) SSMR3HandleHostOSAndArch(PSSMHANDLE pSSM);
+VMMR3_INT_DECL(int) SSMR3HandleSetGCPtrSize(PSSMHANDLE pSSM, unsigned cbGCPtr);
+VMMR3DECL(void) SSMR3HandleReportLivePercent(PSSMHANDLE pSSM, unsigned uPercent);
+VMMR3DECL(int) SSMR3Cancel(PVM pVM);
+
+
+/** Save operations.
+ * @{
+ */
+VMMR3DECL(int) SSMR3PutStruct(PSSMHANDLE pSSM, const void *pvStruct, PCSSMFIELD paFields);
+VMMR3DECL(int) SSMR3PutStructEx(PSSMHANDLE pSSM, const void *pvStruct, size_t cbStruct, uint32_t fFlags, PCSSMFIELD paFields, void *pvUser);
+VMMR3DECL(int) SSMR3PutBool(PSSMHANDLE pSSM, bool fBool);
+VMMR3DECL(int) SSMR3PutU8(PSSMHANDLE pSSM, uint8_t u8);
+VMMR3DECL(int) SSMR3PutS8(PSSMHANDLE pSSM, int8_t i8);
+VMMR3DECL(int) SSMR3PutU16(PSSMHANDLE pSSM, uint16_t u16);
+VMMR3DECL(int) SSMR3PutS16(PSSMHANDLE pSSM, int16_t i16);
+VMMR3DECL(int) SSMR3PutU32(PSSMHANDLE pSSM, uint32_t u32);
+VMMR3DECL(int) SSMR3PutS32(PSSMHANDLE pSSM, int32_t i32);
+VMMR3DECL(int) SSMR3PutU64(PSSMHANDLE pSSM, uint64_t u64);
+VMMR3DECL(int) SSMR3PutS64(PSSMHANDLE pSSM, int64_t i64);
+VMMR3DECL(int) SSMR3PutU128(PSSMHANDLE pSSM, uint128_t u128);
+VMMR3DECL(int) SSMR3PutS128(PSSMHANDLE pSSM, int128_t i128);
+VMMR3DECL(int) SSMR3PutUInt(PSSMHANDLE pSSM, RTUINT u);
+VMMR3DECL(int) SSMR3PutSInt(PSSMHANDLE pSSM, RTINT i);
+VMMR3DECL(int) SSMR3PutGCUInt(PSSMHANDLE pSSM, RTGCUINT u);
+VMMR3DECL(int) SSMR3PutGCUIntReg(PSSMHANDLE pSSM, RTGCUINTREG u);
+VMMR3DECL(int) SSMR3PutGCPhys32(PSSMHANDLE pSSM, RTGCPHYS32 GCPhys);
+VMMR3DECL(int) SSMR3PutGCPhys64(PSSMHANDLE pSSM, RTGCPHYS64 GCPhys);
+VMMR3DECL(int) SSMR3PutGCPhys(PSSMHANDLE pSSM, RTGCPHYS GCPhys);
+VMMR3DECL(int) SSMR3PutGCPtr(PSSMHANDLE pSSM, RTGCPTR GCPtr);
+VMMR3DECL(int) SSMR3PutGCUIntPtr(PSSMHANDLE pSSM, RTGCUINTPTR GCPtr);
+VMMR3DECL(int) SSMR3PutRCPtr(PSSMHANDLE pSSM, RTRCPTR RCPtr);
+VMMR3DECL(int) SSMR3PutIOPort(PSSMHANDLE pSSM, RTIOPORT IOPort);
+VMMR3DECL(int) SSMR3PutSel(PSSMHANDLE pSSM, RTSEL Sel);
+VMMR3DECL(int) SSMR3PutMem(PSSMHANDLE pSSM, const void *pv, size_t cb);
+VMMR3DECL(int) SSMR3PutStrZ(PSSMHANDLE pSSM, const char *psz);
+/** @} */
+
+
+
+/** Load operations.
+ * @{
+ */
+VMMR3DECL(int) SSMR3GetStruct(PSSMHANDLE pSSM, void *pvStruct, PCSSMFIELD paFields);
+VMMR3DECL(int) SSMR3GetStructEx(PSSMHANDLE pSSM, void *pvStruct, size_t cbStruct, uint32_t fFlags, PCSSMFIELD paFields, void *pvUser);
+VMMR3DECL(int) SSMR3GetBool(PSSMHANDLE pSSM, bool *pfBool);
+VMMR3DECL(int) SSMR3GetU8(PSSMHANDLE pSSM, uint8_t *pu8);
+VMMR3DECL(int) SSMR3GetS8(PSSMHANDLE pSSM, int8_t *pi8);
+VMMR3DECL(int) SSMR3GetU16(PSSMHANDLE pSSM, uint16_t *pu16);
+VMMR3DECL(int) SSMR3GetS16(PSSMHANDLE pSSM, int16_t *pi16);
+VMMR3DECL(int) SSMR3GetU32(PSSMHANDLE pSSM, uint32_t *pu32);
+VMMR3DECL(int) SSMR3GetS32(PSSMHANDLE pSSM, int32_t *pi32);
+VMMR3DECL(int) SSMR3GetU64(PSSMHANDLE pSSM, uint64_t *pu64);
+VMMR3DECL(int) SSMR3GetS64(PSSMHANDLE pSSM, int64_t *pi64);
+VMMR3DECL(int) SSMR3GetU128(PSSMHANDLE pSSM, uint128_t *pu128);
+VMMR3DECL(int) SSMR3GetS128(PSSMHANDLE pSSM, int128_t *pi128);
+VMMR3DECL(int) SSMR3GetUInt(PSSMHANDLE pSSM, PRTUINT pu);
+VMMR3DECL(int) SSMR3GetSInt(PSSMHANDLE pSSM, PRTINT pi);
+VMMR3DECL(int) SSMR3GetGCUInt(PSSMHANDLE pSSM, PRTGCUINT pu);
+VMMR3DECL(int) SSMR3GetGCUIntReg(PSSMHANDLE pSSM, PRTGCUINTREG pu);
+VMMR3DECL(int) SSMR3GetGCPhys32(PSSMHANDLE pSSM, PRTGCPHYS32 pGCPhys);
+VMMR3DECL(int) SSMR3GetGCPhys64(PSSMHANDLE pSSM, PRTGCPHYS64 pGCPhys);
+VMMR3DECL(int) SSMR3GetGCPhys(PSSMHANDLE pSSM, PRTGCPHYS pGCPhys);
+VMMR3DECL(int) SSMR3GetGCPtr(PSSMHANDLE pSSM, PRTGCPTR pGCPtr);
+VMMR3DECL(int) SSMR3GetGCUIntPtr(PSSMHANDLE pSSM, PRTGCUINTPTR pGCPtr);
+VMMR3DECL(int) SSMR3GetRCPtr(PSSMHANDLE pSSM, PRTRCPTR pRCPtr);
+VMMR3DECL(int) SSMR3GetIOPort(PSSMHANDLE pSSM, PRTIOPORT pIOPort);
+VMMR3DECL(int) SSMR3GetSel(PSSMHANDLE pSSM, PRTSEL pSel);
+VMMR3DECL(int) SSMR3GetMem(PSSMHANDLE pSSM, void *pv, size_t cb);
+VMMR3DECL(int) SSMR3GetStrZ(PSSMHANDLE pSSM, char *psz, size_t cbMax);
+VMMR3DECL(int) SSMR3GetStrZEx(PSSMHANDLE pSSM, char *psz, size_t cbMax, size_t *pcbStr);
+VMMR3DECL(int) SSMR3GetTimer(PSSMHANDLE pSSM, PTMTIMER pTimer);
+VMMR3DECL(int) SSMR3Skip(PSSMHANDLE pSSM, size_t cb);
+VMMR3DECL(int) SSMR3SkipToEndOfUnit(PSSMHANDLE pSSM);
+VMMR3DECL(int) SSMR3SetLoadError(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...);
+VMMR3DECL(int) SSMR3SetLoadErrorV(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va);
+VMMR3DECL(int) SSMR3SetCfgError(PSSMHANDLE pSSM, RT_SRC_POS_DECL, const char *pszFormat, ...);
+
+/** @} */
+
+/** @} */
+#endif /* IN_RING3 */
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/stam.h b/include/VBox/vmm/stam.h
new file mode 100644
index 00000000..c25c606f
--- /dev/null
+++ b/include/VBox/vmm/stam.h
@@ -0,0 +1,1265 @@
+/** @file
+ * STAM - Statistics Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_stam_h
+#define ___VBox_vmm_stam_h
+
+#include <VBox/types.h>
+#include <iprt/stdarg.h>
+#ifdef _MSC_VER
+# if _MSC_VER >= 1400
+# include <intrin.h>
+# endif
+#endif
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_stam The Statistics Manager API
+ * @{
+ */
+
+#if defined(VBOX_WITHOUT_RELEASE_STATISTICS) && defined(VBOX_WITH_STATISTICS)
+# error "Both VBOX_WITHOUT_RELEASE_STATISTICS and VBOX_WITH_STATISTICS are defined! Make up your mind!"
+#endif
+
+
+/** @def STAM_GET_TS
+ * Gets the CPU timestamp counter.
+ *
+ * @param u64 The 64-bit variable which the timestamp shall be saved in.
+ */
+#ifdef __GNUC__
+# if defined(RT_ARCH_X86)
+ /* This produces optimal assembler code for x86 but does not work for AMD64 ('A' means 'either rax or rdx') */
+# define STAM_GET_TS(u64) __asm__ __volatile__ ("rdtsc\n\t" : "=A" (u64))
+# elif defined(RT_ARCH_AMD64)
+# define STAM_GET_TS(u64) \
+ do { uint64_t low; uint64_t high; \
+ __asm__ __volatile__ ("rdtsc\n\t" : "=a"(low), "=d"(high)); \
+ (u64) = ((high << 32) | low); \
+ } while (0)
+# endif
+#else
+# if _MSC_VER >= 1400
+# pragma intrinsic(__rdtsc)
+# define STAM_GET_TS(u64) \
+ do { (u64) = __rdtsc(); } while (0)
+# else
+# define STAM_GET_TS(u64) \
+ do { \
+ uint64_t u64Tmp; \
+ __asm { \
+ __asm rdtsc \
+ __asm mov dword ptr [u64Tmp], eax \
+ __asm mov dword ptr [u64Tmp + 4], edx \
+ } \
+ (u64) = u64Tmp; \
+ } while (0)
+# endif
+#endif
+
+
+/** @def STAM_REL_STATS
+ * Code for inclusion only when VBOX_WITH_STATISTICS is defined.
+ * @param code A code block enclosed in {}.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_STATS(code) do code while(0)
+#else
+# define STAM_REL_STATS(code) do {} while(0)
+#endif
+/** @def STAM_STATS
+ * Code for inclusion only when VBOX_WITH_STATISTICS is defined.
+ * @param code A code block enclosed in {}.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_STATS(code) STAM_REL_STATS(code)
+#else
+# define STAM_STATS(code) do {} while(0)
+#endif
+
+
+/**
+ * Sample type.
+ */
+typedef enum STAMTYPE
+{
+ /** Invalid entry. */
+ STAMTYPE_INVALID = 0,
+ /** Generic counter. */
+ STAMTYPE_COUNTER,
+ /** Profiling of an function. */
+ STAMTYPE_PROFILE,
+ /** Profiling of an operation. */
+ STAMTYPE_PROFILE_ADV,
+ /** Ratio of A to B, uint32_t types. Not reset. */
+ STAMTYPE_RATIO_U32,
+ /** Ratio of A to B, uint32_t types. Reset both to 0. */
+ STAMTYPE_RATIO_U32_RESET,
+ /** Callback. */
+ STAMTYPE_CALLBACK,
+ /** Generic unsigned 8-bit value. Not reset. */
+ STAMTYPE_U8,
+ /** Generic unsigned 8-bit value. Reset to 0. */
+ STAMTYPE_U8_RESET,
+ /** Generic hexadecimal unsigned 8-bit value. Not reset. */
+ STAMTYPE_X8,
+ /** Generic hexadecimal unsigned 8-bit value. Reset to 0. */
+ STAMTYPE_X8_RESET,
+ /** Generic unsigned 16-bit value. Not reset. */
+ STAMTYPE_U16,
+ /** Generic unsigned 16-bit value. Reset to 0. */
+ STAMTYPE_U16_RESET,
+ /** Generic hexadecimal unsigned 16-bit value. Not reset. */
+ STAMTYPE_X16,
+ /** Generic hexadecimal unsigned 16-bit value. Reset to 0. */
+ STAMTYPE_X16_RESET,
+ /** Generic unsigned 32-bit value. Not reset. */
+ STAMTYPE_U32,
+ /** Generic unsigned 32-bit value. Reset to 0. */
+ STAMTYPE_U32_RESET,
+ /** Generic hexadecimal unsigned 32-bit value. Not reset. */
+ STAMTYPE_X32,
+ /** Generic hexadecimal unsigned 32-bit value. Reset to 0. */
+ STAMTYPE_X32_RESET,
+ /** Generic unsigned 64-bit value. Not reset. */
+ STAMTYPE_U64,
+ /** Generic unsigned 64-bit value. Reset to 0. */
+ STAMTYPE_U64_RESET,
+ /** Generic hexadecimal unsigned 64-bit value. Not reset. */
+ STAMTYPE_X64,
+ /** Generic hexadecimal unsigned 64-bit value. Reset to 0. */
+ STAMTYPE_X64_RESET,
+ /** Generic boolean value. Not reset. */
+ STAMTYPE_BOOL,
+ /** Generic boolean value. Reset to false. */
+ STAMTYPE_BOOL_RESET,
+ /** The end (exclusive). */
+ STAMTYPE_END
+} STAMTYPE;
+
+/**
+ * Sample visibility type.
+ */
+typedef enum STAMVISIBILITY
+{
+ /** Invalid entry. */
+ STAMVISIBILITY_INVALID = 0,
+ /** Always visible. */
+ STAMVISIBILITY_ALWAYS,
+ /** Only visible when used (/hit). */
+ STAMVISIBILITY_USED,
+ /** Not visible in the GUI. */
+ STAMVISIBILITY_NOT_GUI,
+ /** The end (exclusive). */
+ STAMVISIBILITY_END
+} STAMVISIBILITY;
+
+/**
+ * Sample unit.
+ */
+typedef enum STAMUNIT
+{
+ /** Invalid entry .*/
+ STAMUNIT_INVALID = 0,
+ /** No unit. */
+ STAMUNIT_NONE,
+ /** Number of calls. */
+ STAMUNIT_CALLS,
+ /** Count of whatever. */
+ STAMUNIT_COUNT,
+ /** Count of bytes. */
+ STAMUNIT_BYTES,
+ /** Count of bytes. */
+ STAMUNIT_PAGES,
+ /** Error count. */
+ STAMUNIT_ERRORS,
+ /** Number of occurences. */
+ STAMUNIT_OCCURENCES,
+ /** Ticks. */
+ STAMUNIT_TICKS,
+ /** Ticks per call. */
+ STAMUNIT_TICKS_PER_CALL,
+ /** Ticks per occurence. */
+ STAMUNIT_TICKS_PER_OCCURENCE,
+ /** Ratio of good vs. bad. */
+ STAMUNIT_GOOD_BAD,
+ /** Megabytes. */
+ STAMUNIT_MEGABYTES,
+ /** Kilobytes. */
+ STAMUNIT_KILOBYTES,
+ /** Nano seconds. */
+ STAMUNIT_NS,
+ /** Nanoseconds per call. */
+ STAMUNIT_NS_PER_CALL,
+ /** Nanoseconds per call. */
+ STAMUNIT_NS_PER_OCCURENCE,
+ /** Percentage. */
+ STAMUNIT_PCT,
+ /** Hertz. */
+ STAMUNIT_HZ,
+ /** The end (exclusive). */
+ STAMUNIT_END
+} STAMUNIT;
+
+
+/** @def STAM_REL_U8_INC
+ * Increments a uint8_t sample by one.
+ *
+ * @param pCounter Pointer to the uint8_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U8_INC(pCounter) \
+ do { ++*(pCounter); } while (0)
+#else
+# define STAM_REL_U8_INC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U8_INC
+ * Increments a uint8_t sample by one.
+ *
+ * @param pCounter Pointer to the uint8_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U8_INC(pCounter) STAM_REL_U8_INC(pCounter)
+#else
+# define STAM_U8_INC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U8_DEC
+ * Decrements a uint8_t sample by one.
+ *
+ * @param pCounter Pointer to the uint8_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U8_DEC(pCounter) \
+ do { --*(pCounter); } while (0)
+#else
+# define STAM_REL_U8_DEC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U8_DEC
+ * Decrements a uint8_t sample by one.
+ *
+ * @param pCounter Pointer to the uint8_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U8_DEC(pCounter) STAM_REL_U8_DEC(pCounter)
+#else
+# define STAM_U8_DEC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U8_ADD
+ * Increments a uint8_t sample by a value.
+ *
+ * @param pCounter Pointer to the uint8_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U8_ADD(pCounter, Addend) \
+ do { *(pCounter) += (Addend); } while (0)
+#else
+# define STAM_REL_U8_ADD(pCounter, Addend) do { } while (0)
+#endif
+/** @def STAM_U8_ADD
+ * Increments a uint8_t sample by a value.
+ *
+ * @param pCounter Pointer to the uint8_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U8_ADD(pCounter, Addend) STAM_REL_U8_ADD(pCounter, Addend
+#else
+# define STAM_U8_ADD(pCounter, Addend) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U16_INC
+ * Increments a uint16_t sample by one.
+ *
+ * @param pCounter Pointer to the uint16_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U16_INC(pCounter) \
+ do { ++*(pCounter); } while (0)
+#else
+# define STAM_REL_U16_INC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U16_INC
+ * Increments a uint16_t sample by one.
+ *
+ * @param pCounter Pointer to the uint16_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U16_INC(pCounter) STAM_REL_U16_INC(pCounter)
+#else
+# define STAM_U16_INC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U16_DEC
+ * Decrements a uint16_t sample by one.
+ *
+ * @param pCounter Pointer to the uint16_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U16_DEC(pCounter) \
+ do { --*(pCounter); } while (0)
+#else
+# define STAM_REL_U16_DEC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U16_DEC
+ * Decrements a uint16_t sample by one.
+ *
+ * @param pCounter Pointer to the uint16_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U16_DEC(pCounter) STAM_REL_U16_DEC(pCounter)
+#else
+# define STAM_U16_DEC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U16_INC
+ * Increments a uint16_t sample by a value.
+ *
+ * @param pCounter Pointer to the uint16_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U16_ADD(pCounter, Addend) \
+ do { *(pCounter) += (Addend); } while (0)
+#else
+# define STAM_REL_U16_ADD(pCounter, Addend) do { } while (0)
+#endif
+/** @def STAM_U16_INC
+ * Increments a uint16_t sample by a value.
+ *
+ * @param pCounter Pointer to the uint16_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U16_ADD(pCounter, Addend) STAM_REL_U16_ADD(pCounter, Addend)
+#else
+# define STAM_U16_ADD(pCounter, Addend) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U32_INC
+ * Increments a uint32_t sample by one.
+ *
+ * @param pCounter Pointer to the uint32_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U32_INC(pCounter) \
+ do { ++*(pCounter); } while (0)
+#else
+# define STAM_REL_U32_INC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U32_INC
+ * Increments a uint32_t sample by one.
+ *
+ * @param pCounter Pointer to the uint32_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U32_INC(pCounter) STAM_REL_U32_INC(pCounter)
+#else
+# define STAM_U32_INC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U32_DEC
+ * Decrements a uint32_t sample by one.
+ *
+ * @param pCounter Pointer to the uint32_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U32_DEC(pCounter) \
+ do { --*(pCounter); } while (0)
+#else
+# define STAM_REL_U32_DEC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U32_DEC
+ * Decrements a uint32_t sample by one.
+ *
+ * @param pCounter Pointer to the uint32_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U32_DEC(pCounter) STAM_REL_U32_DEC(pCounter)
+#else
+# define STAM_U32_DEC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U32_ADD
+ * Increments a uint32_t sample by value.
+ *
+ * @param pCounter Pointer to the uint32_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U32_ADD(pCounter, Addend) \
+ do { *(pCounter) += (Addend); } while (0)
+#else
+# define STAM_REL_U32_ADD(pCounter, Addend) do { } while (0)
+#endif
+/** @def STAM_U32_ADD
+ * Increments a uint32_t sample by value.
+ *
+ * @param pCounter Pointer to the uint32_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U32_ADD(pCounter, Addend) STAM_REL_U32_ADD(pCounter, Addend)
+#else
+# define STAM_U32_ADD(pCounter, Addend) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U64_INC
+ * Increments a uint64_t sample by one.
+ *
+ * @param pCounter Pointer to the uint64_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U64_INC(pCounter) \
+ do { ++*(pCounter); } while (0)
+#else
+# define STAM_REL_U64_INC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U64_INC
+ * Increments a uint64_t sample by one.
+ *
+ * @param pCounter Pointer to the uint64_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U64_INC(pCounter) STAM_REL_U64_INC(pCounter)
+#else
+# define STAM_U64_INC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U64_DEC
+ * Decrements a uint64_t sample by one.
+ *
+ * @param pCounter Pointer to the uint64_t variable to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U64_DEC(pCounter) \
+ do { --*(pCounter); } while (0)
+#else
+# define STAM_REL_U64_DEC(pCounter) do { } while (0)
+#endif
+/** @def STAM_U64_DEC
+ * Decrements a uint64_t sample by one.
+ *
+ * @param pCounter Pointer to the uint64_t variable to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U64_DEC(pCounter) STAM_REL_U64_DEC(pCounter)
+#else
+# define STAM_U64_DEC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_U64_ADD
+ * Increments a uint64_t sample by a value.
+ *
+ * @param pCounter Pointer to the uint64_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_U64_ADD(pCounter, Addend) \
+ do { *(pCounter) += (Addend); } while (0)
+#else
+# define STAM_REL_U64_ADD(pCounter, Addend) do { } while (0)
+#endif
+/** @def STAM_U64_ADD
+ * Increments a uint64_t sample by a value.
+ *
+ * @param pCounter Pointer to the uint64_t variable to operate on.
+ * @param Addend The value to add.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_U64_ADD(pCounter, Addend) STAM_REL_U64_ADD(pCounter, Addend)
+#else
+# define STAM_U64_ADD(pCounter, Addend) do { } while (0)
+#endif
+
+
+/**
+ * Counter sample - STAMTYPE_COUNTER.
+ */
+typedef struct STAMCOUNTER
+{
+ /** The current count. */
+ volatile uint64_t c;
+} STAMCOUNTER;
+/** Pointer to a counter. */
+typedef STAMCOUNTER *PSTAMCOUNTER;
+/** Pointer to a const counter. */
+typedef const STAMCOUNTER *PCSTAMCOUNTER;
+
+
+/** @def STAM_REL_COUNTER_INC
+ * Increments a counter sample by one.
+ *
+ * @param pCounter Pointer to the STAMCOUNTER structure to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_COUNTER_INC(pCounter) \
+ do { (pCounter)->c++; } while (0)
+#else
+# define STAM_REL_COUNTER_INC(pCounter) do { } while (0)
+#endif
+/** @def STAM_COUNTER_INC
+ * Increments a counter sample by one.
+ *
+ * @param pCounter Pointer to the STAMCOUNTER structure to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_COUNTER_INC(pCounter) STAM_REL_COUNTER_INC(pCounter)
+#else
+# define STAM_COUNTER_INC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_COUNTER_DEC
+ * Decrements a counter sample by one.
+ *
+ * @param pCounter Pointer to the STAMCOUNTER structure to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_COUNTER_DEC(pCounter) \
+ do { (pCounter)->c--; } while (0)
+#else
+# define STAM_REL_COUNTER_DEC(pCounter) do { } while (0)
+#endif
+/** @def STAM_COUNTER_DEC
+ * Decrements a counter sample by one.
+ *
+ * @param pCounter Pointer to the STAMCOUNTER structure to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_COUNTER_DEC(pCounter) STAM_REL_COUNTER_DEC(pCounter)
+#else
+# define STAM_COUNTER_DEC(pCounter) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_COUNTER_ADD
+ * Increments a counter sample by a value.
+ *
+ * @param pCounter Pointer to the STAMCOUNTER structure to operate on.
+ * @param Addend The value to add to the counter.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_COUNTER_ADD(pCounter, Addend) \
+ do { (pCounter)->c += (Addend); } while (0)
+#else
+# define STAM_REL_COUNTER_ADD(pCounter, Addend) do { } while (0)
+#endif
+/** @def STAM_COUNTER_ADD
+ * Increments a counter sample by a value.
+ *
+ * @param pCounter Pointer to the STAMCOUNTER structure to operate on.
+ * @param Addend The value to add to the counter.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_COUNTER_ADD(pCounter, Addend) STAM_REL_COUNTER_ADD(pCounter, Addend)
+#else
+# define STAM_COUNTER_ADD(pCounter, Addend) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_COUNTER_RESET
+ * Resets the statistics sample.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_COUNTER_RESET(pCounter) do { (pCounter)->c = 0; } while (0)
+#else
+# define STAM_REL_COUNTER_RESET(pCounter) do { } while (0)
+#endif
+/** @def STAM_COUNTER_RESET
+ * Resets the statistics sample.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_COUNTER_RESET(pCounter) STAM_REL_COUNTER_RESET(pCounter)
+#else
+# define STAM_COUNTER_RESET(pCounter) do { } while (0)
+#endif
+
+
+
+/**
+ * Profiling sample - STAMTYPE_PROFILE.
+ */
+typedef struct STAMPROFILE
+{
+ /** Number of periods. */
+ volatile uint64_t cPeriods;
+ /** Total count of ticks. */
+ volatile uint64_t cTicks;
+ /** Maximum tick count during a sampling. */
+ volatile uint64_t cTicksMax;
+ /** Minimum tick count during a sampling. */
+ volatile uint64_t cTicksMin;
+} STAMPROFILE;
+/** Pointer to a profile sample. */
+typedef STAMPROFILE *PSTAMPROFILE;
+/** Pointer to a const profile sample. */
+typedef const STAMPROFILE *PCSTAMPROFILE;
+
+
+/** @def STAM_REL_PROFILE_ADD_PERIOD
+ * Adds a period.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param cTicksInPeriod The number of tick (or whatever) of the preiod
+ * being added. This is only referenced once.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADD_PERIOD(pProfile, cTicksInPeriod) \
+ do { \
+ uint64_t const StamPrefix_cTicks = (cTicksInPeriod); \
+ (pProfile)->cTicks += StamPrefix_cTicks; \
+ (pProfile)->cPeriods++; \
+ if ((pProfile)->cTicksMax < StamPrefix_cTicks) \
+ (pProfile)->cTicksMax = StamPrefix_cTicks; \
+ if ((pProfile)->cTicksMin > StamPrefix_cTicks) \
+ (pProfile)->cTicksMin = StamPrefix_cTicks; \
+ } while (0)
+#else
+# define STAM_REL_PROFILE_ADD_PERIOD(pProfile, cTicksInPeriod) do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADD_PERIOD
+ * Adds a period.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param cTicksInPeriod The number of tick (or whatever) of the preiod
+ * being added. This is only referenced once.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADD_PERIOD(pProfile, cTicksInPeriod) STAM_REL_PROFILE_ADD_PERIOD(pProfile, cTicksInPeriod)
+#else
+# define STAM_PROFILE_ADD_PERIOD(pProfile, cTicksInPeriod) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_START
+ * Samples the start time of a profiling period.
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ *
+ * @remarks Declears a stack variable that will be used by related macros.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_START(pProfile, Prefix) \
+ uint64_t Prefix##_tsStart; \
+ STAM_GET_TS(Prefix##_tsStart)
+#else
+# define STAM_REL_PROFILE_START(pProfile, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_START
+ * Samples the start time of a profiling period.
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ *
+ * @remarks Declears a stack variable that will be used by related macros.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_START(pProfile, Prefix) STAM_REL_PROFILE_START(pProfile, Prefix)
+#else
+# define STAM_PROFILE_START(pProfile, Prefix) do { } while (0)
+#endif
+
+/** @def STAM_REL_PROFILE_STOP
+ * Samples the stop time of a profiling period and updates the sample.
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_STOP(pProfile, Prefix) \
+ do { \
+ uint64_t Prefix##_cTicks; \
+ STAM_GET_TS(Prefix##_cTicks); \
+ Prefix##_cTicks -= Prefix##_tsStart; \
+ (pProfile)->cTicks += Prefix##_cTicks; \
+ (pProfile)->cPeriods++; \
+ if ((pProfile)->cTicksMax < Prefix##_cTicks) \
+ (pProfile)->cTicksMax = Prefix##_cTicks; \
+ if ((pProfile)->cTicksMin > Prefix##_cTicks) \
+ (pProfile)->cTicksMin = Prefix##_cTicks; \
+ } while (0)
+#else
+# define STAM_REL_PROFILE_STOP(pProfile, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_STOP
+ * Samples the stop time of a profiling period and updates the sample.
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_STOP(pProfile, Prefix) STAM_REL_PROFILE_STOP(pProfile, Prefix)
+#else
+# define STAM_PROFILE_STOP(pProfile, Prefix) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_STOP_EX
+ * Samples the stop time of a profiling period and updates both the sample
+ * and an attribution sample.
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param pProfile2 Pointer to the STAMPROFILE structure which this
+ * interval should be attributed to as well. This may be NULL.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_STOP_EX(pProfile, pProfile2, Prefix) \
+ do { \
+ uint64_t Prefix##_cTicks; \
+ STAM_GET_TS(Prefix##_cTicks); \
+ Prefix##_cTicks -= Prefix##_tsStart; \
+ (pProfile)->cTicks += Prefix##_cTicks; \
+ (pProfile)->cPeriods++; \
+ if ((pProfile)->cTicksMax < Prefix##_cTicks) \
+ (pProfile)->cTicksMax = Prefix##_cTicks; \
+ if ((pProfile)->cTicksMin > Prefix##_cTicks) \
+ (pProfile)->cTicksMin = Prefix##_cTicks; \
+ \
+ if ((pProfile2)) \
+ { \
+ (pProfile2)->cTicks += Prefix##_cTicks; \
+ (pProfile2)->cPeriods++; \
+ if ((pProfile2)->cTicksMax < Prefix##_cTicks) \
+ (pProfile2)->cTicksMax = Prefix##_cTicks; \
+ if ((pProfile2)->cTicksMin > Prefix##_cTicks) \
+ (pProfile2)->cTicksMin = Prefix##_cTicks; \
+ } \
+ } while (0)
+#else
+# define STAM_REL_PROFILE_STOP_EX(pProfile, pProfile2, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_STOP_EX
+ * Samples the stop time of a profiling period and updates both the sample
+ * and an attribution sample.
+ *
+ * @param pProfile Pointer to the STAMPROFILE structure to operate on.
+ * @param pProfile2 Pointer to the STAMPROFILE structure which this
+ * interval should be attributed to as well. This may be NULL.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_STOP_EX(pProfile, pProfile2, Prefix) STAM_REL_PROFILE_STOP_EX(pProfile, pProfile2, Prefix)
+#else
+# define STAM_PROFILE_STOP_EX(pProfile, pProfile2, Prefix) do { } while (0)
+#endif
+
+
+/**
+ * Advanced profiling sample - STAMTYPE_PROFILE_ADV.
+ *
+ * Identical to a STAMPROFILE sample, but the start timestamp
+ * is stored after the STAMPROFILE structure so the sampling
+ * can start and stop in different functions.
+ */
+typedef struct STAMPROFILEADV
+{
+ /** The STAMPROFILE core. */
+ STAMPROFILE Core;
+ /** The start timestamp. */
+ volatile uint64_t tsStart;
+} STAMPROFILEADV;
+/** Pointer to a advanced profile sample. */
+typedef STAMPROFILEADV *PSTAMPROFILEADV;
+/** Pointer to a const advanced profile sample. */
+typedef const STAMPROFILEADV *PCSTAMPROFILEADV;
+
+
+/** @def STAM_REL_PROFILE_ADV_START
+ * Samples the start time of a profiling period.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_START(pProfileAdv, Prefix) \
+ STAM_GET_TS((pProfileAdv)->tsStart)
+#else
+# define STAM_REL_PROFILE_ADV_START(pProfileAdv, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADV_START
+ * Samples the start time of a profiling period.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_START(pProfileAdv, Prefix) STAM_REL_PROFILE_ADV_START(pProfileAdv, Prefix)
+#else
+# define STAM_PROFILE_ADV_START(pProfileAdv, Prefix) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_ADV_STOP
+ * Samples the stop time of a profiling period (if running) and updates the
+ * sample.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_STOP(pProfileAdv, Prefix) \
+ do { \
+ if ((pProfileAdv)->tsStart) \
+ { \
+ uint64_t Prefix##_cTicks; \
+ STAM_GET_TS(Prefix##_cTicks); \
+ Prefix##_cTicks -= (pProfileAdv)->tsStart; \
+ (pProfileAdv)->tsStart = 0; \
+ (pProfileAdv)->Core.cTicks += Prefix##_cTicks; \
+ (pProfileAdv)->Core.cPeriods++; \
+ if ((pProfileAdv)->Core.cTicksMax < Prefix##_cTicks) \
+ (pProfileAdv)->Core.cTicksMax = Prefix##_cTicks; \
+ if ((pProfileAdv)->Core.cTicksMin > Prefix##_cTicks) \
+ (pProfileAdv)->Core.cTicksMin = Prefix##_cTicks; \
+ } \
+ } while (0)
+#else
+# define STAM_REL_PROFILE_ADV_STOP(pProfileAdv, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADV_STOP
+ * Samples the stop time of a profiling period (if running) and updates the
+ * sample.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_STOP(pProfileAdv, Prefix) STAM_REL_PROFILE_ADV_STOP(pProfileAdv, Prefix)
+#else
+# define STAM_PROFILE_ADV_STOP(pProfileAdv, Prefix) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_ADV_STOP_START
+ * Stops one profile counter (if running) and starts another one.
+ *
+ * @param pProfileAdv1 Pointer to the STAMPROFILEADV structure to stop.
+ * @param pProfileAdv2 Pointer to the STAMPROFILEADV structure to start.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_STOP_START(pProfileAdv1, pProfileAdv2, Prefix) \
+ do { \
+ uint64_t Prefix##_cTicks; \
+ STAM_GET_TS(Prefix##_cTicks); \
+ (pProfileAdv2)->tsStart = Prefix##_cTicks; \
+ if ((pProfileAdv1)->tsStart) \
+ { \
+ Prefix##_cTicks -= (pProfileAdv1)->tsStart; \
+ (pProfileAdv1)->tsStart = 0; \
+ (pProfileAdv1)->Core.cTicks += Prefix##_cTicks; \
+ (pProfileAdv1)->Core.cPeriods++; \
+ if ((pProfileAdv1)->Core.cTicksMax < Prefix##_cTicks) \
+ (pProfileAdv1)->Core.cTicksMax = Prefix##_cTicks; \
+ if ((pProfileAdv1)->Core.cTicksMin > Prefix##_cTicks) \
+ (pProfileAdv1)->Core.cTicksMin = Prefix##_cTicks; \
+ } \
+ } while (0)
+#else
+# define STAM_REL_PROFILE_ADV_STOP_START(pProfileAdv1, pProfileAdv2, Prefix) \
+ do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADV_STOP_START
+ * Samples the stop time of a profiling period (if running) and updates the
+ * sample.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_STOP_START(pProfileAdv1, pProfileAdv2, Prefix) \
+ STAM_REL_PROFILE_ADV_STOP_START(pProfileAdv1, pProfileAdv2, Prefix)
+#else
+# define STAM_PROFILE_ADV_STOP_START(pProfileAdv1, pProfileAdv2, Prefix) \
+ do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_ADV_SUSPEND
+ * Suspends the sampling for a while. This can be useful to exclude parts
+ * covered by other samples without screwing up the count, and average+min times.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables. The prefix
+ * must match that of the resume one since it stores the
+ * suspend time in a stack variable.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_SUSPEND(pProfileAdv, Prefix) \
+ uint64_t Prefix##_tsSuspend; \
+ STAM_GET_TS(Prefix##_tsSuspend)
+#else
+# define STAM_REL_PROFILE_ADV_SUSPEND(pProfileAdv, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADV_SUSPEND
+ * Suspends the sampling for a while. This can be useful to exclude parts
+ * covered by other samples without screwing up the count, and average+min times.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables. The prefix
+ * must match that of the resume one since it stores the
+ * suspend time in a stack variable.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_SUSPEND(pProfileAdv, Prefix) STAM_REL_PROFILE_ADV_SUSPEND(pProfileAdv, Prefix)
+#else
+# define STAM_PROFILE_ADV_SUSPEND(pProfileAdv, Prefix) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_ADV_RESUME
+ * Counter to STAM_REL_PROFILE_ADV_SUSPEND.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables. This must
+ * match the one used with the SUSPEND!
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_RESUME(pProfileAdv, Prefix) \
+ do { \
+ uint64_t Prefix##_tsNow; \
+ STAM_GET_TS(Prefix##_tsNow); \
+ (pProfileAdv)->tsStart += Prefix##_tsNow - Prefix##_tsSuspend; \
+ } while (0)
+#else
+# define STAM_REL_PROFILE_ADV_RESUME(pProfileAdv, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADV_RESUME
+ * Counter to STAM_PROFILE_ADV_SUSPEND.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param Prefix Identifier prefix used to internal variables. This must
+ * match the one used with the SUSPEND!
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_RESUME(pProfileAdv, Prefix) STAM_REL_PROFILE_ADV_RESUME(pProfileAdv, Prefix)
+#else
+# define STAM_PROFILE_ADV_RESUME(pProfileAdv, Prefix) do { } while (0)
+#endif
+
+
+/** @def STAM_REL_PROFILE_ADV_STOP_EX
+ * Samples the stop time of a profiling period (if running) and updates both
+ * the sample and an attribution sample.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param pProfile2 Pointer to the STAMPROFILE structure which this
+ * interval should be attributed to as well. This may be NULL.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_STOP_EX(pProfileAdv, pProfile2, Prefix) \
+ do { \
+ if ((pProfileAdv)->tsStart) \
+ { \
+ uint64_t Prefix##_cTicks; \
+ STAM_GET_TS(Prefix##_cTicks); \
+ Prefix##_cTicks -= (pProfileAdv)->tsStart; \
+ (pProfileAdv)->tsStart = 0; \
+ (pProfileAdv)->Core.cTicks += Prefix##_cTicks; \
+ (pProfileAdv)->Core.cPeriods++; \
+ if ((pProfileAdv)->Core.cTicksMax < Prefix##_cTicks) \
+ (pProfileAdv)->Core.cTicksMax = Prefix##_cTicks; \
+ if ((pProfileAdv)->Core.cTicksMin > Prefix##_cTicks) \
+ (pProfileAdv)->Core.cTicksMin = Prefix##_cTicks; \
+ if ((pProfile2)) \
+ { \
+ (pProfile2)->cTicks += Prefix##_cTicks; \
+ (pProfile2)->cPeriods++; \
+ if ((pProfile2)->cTicksMax < Prefix##_cTicks) \
+ (pProfile2)->cTicksMax = Prefix##_cTicks; \
+ if ((pProfile2)->cTicksMin > Prefix##_cTicks) \
+ (pProfile2)->cTicksMin = Prefix##_cTicks; \
+ } \
+ } \
+ } while (0)
+#else
+# define STAM_REL_PROFILE_ADV_STOP_EX(pProfileAdv, pProfile2, Prefix) do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADV_STOP_EX
+ * Samples the stop time of a profiling period (if running) and updates both
+ * the sample and an attribution sample.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ * @param pProfile2 Pointer to the STAMPROFILE structure which this
+ * interval should be attributed to as well. This may be NULL.
+ * @param Prefix Identifier prefix used to internal variables.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_STOP_EX(pProfileAdv, pProfile2, Prefix) STAM_REL_PROFILE_ADV_STOP_EX(pProfileAdv, pProfile2, Prefix)
+#else
+# define STAM_PROFILE_ADV_STOP_EX(pProfileAdv, pProfile2, Prefix) do { } while (0)
+#endif
+
+/** @def STAM_REL_PROFILE_ADV_IS_RUNNING
+ * Checks if it is running.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_IS_RUNNING(pProfileAdv) (pProfileAdv)->tsStart
+#else
+# define STAM_REL_PROFILE_ADV_IS_RUNNING(pProfileAdv) (false)
+#endif
+/** @def STAM_PROFILE_ADV_IS_RUNNING
+ * Checks if it is running.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_IS_RUNNING(pProfileAdv) STAM_REL_PROFILE_ADV_IS_RUNNING(pProfileAdv)
+#else
+# define STAM_PROFILE_ADV_IS_RUNNING(pProfileAdv) (false)
+#endif
+
+/** @def STAM_REL_PROFILE_ADV_SET_STOPPED
+ * Marks the profile counter as stopped.
+ *
+ * This is for avoiding screwups in twisty code.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ */
+#ifndef VBOX_WITHOUT_RELEASE_STATISTICS
+# define STAM_REL_PROFILE_ADV_SET_STOPPED(pProfileAdv) do { (pProfileAdv)->tsStart = 0; } while (0)
+#else
+# define STAM_REL_PROFILE_ADV_SET_STOPPED(pProfileAdv) do { } while (0)
+#endif
+/** @def STAM_PROFILE_ADV_SET_STOPPED
+ * Marks the profile counter as stopped.
+ *
+ * This is for avoiding screwups in twisty code.
+ *
+ * @param pProfileAdv Pointer to the STAMPROFILEADV structure to operate on.
+ */
+#ifdef VBOX_WITH_STATISTICS
+# define STAM_PROFILE_ADV_SET_STOPPED(pProfileAdv) STAM_REL_PROFILE_ADV_SET_STOPPED(pProfileAdv)
+#else
+# define STAM_PROFILE_ADV_SET_STOPPED(pProfileAdv) do { } while (0)
+#endif
+
+
+/**
+ * Ratio of A to B, uint32_t types.
+ * @remark Use STAM_STATS or STAM_REL_STATS for modifying A & B values.
+ */
+typedef struct STAMRATIOU32
+{
+ /** Sample A. */
+ uint32_t volatile u32A;
+ /** Sample B. */
+ uint32_t volatile u32B;
+} STAMRATIOU32;
+/** Pointer to a uint32_t ratio. */
+typedef STAMRATIOU32 *PSTAMRATIOU32;
+/** Pointer to const a uint32_t ratio. */
+typedef const STAMRATIOU32 *PCSTAMRATIOU32;
+
+
+
+
+/** @defgroup grp_stam_r3 The STAM Host Context Ring 3 API
+ * @ingroup grp_stam
+ * @{
+ */
+
+VMMR3DECL(int) STAMR3InitUVM(PUVM pUVM);
+VMMR3DECL(void) STAMR3TermUVM(PUVM pUVM);
+VMMR3DECL(int) STAMR3RegisterU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
+VMMR3DECL(int) STAMR3Register(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
+
+/** @def STAM_REL_REG
+ * Registers a statistics sample.
+ *
+ * @param pVM VM Handle.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param pszName Sample name. The name is on this form "/<component>/<sample>".
+ * Further nesting is possible.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ */
+#define STAM_REL_REG(pVM, pvSample, enmType, pszName, enmUnit, pszDesc) \
+ STAM_REL_STATS({ int rcStam = STAMR3Register(pVM, pvSample, enmType, STAMVISIBILITY_ALWAYS, pszName, enmUnit, pszDesc); \
+ AssertRC(rcStam); })
+/** @def STAM_REG
+ * Registers a statistics sample if statistics are enabled.
+ *
+ * @param pVM VM Handle.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param pszName Sample name. The name is on this form "/<component>/<sample>".
+ * Further nesting is possible.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ */
+#define STAM_REG(pVM, pvSample, enmType, pszName, enmUnit, pszDesc) \
+ STAM_STATS({STAM_REL_REG(pVM, pvSample, enmType, pszName, enmUnit, pszDesc);})
+
+/** @def STAM_REL_REG_USED
+ * Registers a statistics sample which only shows when used.
+ *
+ * @param pVM VM Handle.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param pszName Sample name. The name is on this form "/<component>/<sample>".
+ * Further nesting is possible.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ */
+#define STAM_REL_REG_USED(pVM, pvSample, enmType, pszName, enmUnit, pszDesc) \
+ STAM_REL_STATS({ int rcStam = STAMR3Register(pVM, pvSample, enmType, STAMVISIBILITY_USED, pszName, enmUnit, pszDesc); \
+ AssertRC(rcStam);})
+/** @def STAM_REG_USED
+ * Registers a statistics sample which only shows when used, if statistics are enabled.
+ *
+ * @param pVM VM Handle.
+ * @param pvSample Pointer to the sample.
+ * @param enmType Sample type. This indicates what pvSample is pointing at.
+ * @param pszName Sample name. The name is on this form "/<component>/<sample>".
+ * Further nesting is possible.
+ * @param enmUnit Sample unit.
+ * @param pszDesc Sample description.
+ */
+#define STAM_REG_USED(pVM, pvSample, enmType, pszName, enmUnit, pszDesc) \
+ STAM_STATS({ STAM_REL_REG_USED(pVM, pvSample, enmType, pszName, enmUnit, pszDesc); })
+
+VMMR3DECL(int) STAMR3RegisterFU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ const char *pszDesc, const char *pszName, ...);
+VMMR3DECL(int) STAMR3RegisterF(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ const char *pszDesc, const char *pszName, ...);
+VMMR3DECL(int) STAMR3RegisterVU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ const char *pszDesc, const char *pszName, va_list args);
+VMMR3DECL(int) STAMR3RegisterV(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ const char *pszDesc, const char *pszName, va_list args);
+
+/**
+ * Resets the sample.
+ * @param pVM The VM handle.
+ * @param pvSample The sample registered using STAMR3RegisterCallback.
+ */
+typedef void FNSTAMR3CALLBACKRESET(PVM pVM, void *pvSample);
+/** Pointer to a STAM sample reset callback. */
+typedef FNSTAMR3CALLBACKRESET *PFNSTAMR3CALLBACKRESET;
+
+/**
+ * Prints the sample into the buffer.
+ *
+ * @param pVM The VM handle.
+ * @param pvSample The sample registered using STAMR3RegisterCallback.
+ * @param pszBuf The buffer to print into.
+ * @param cchBuf The size of the buffer.
+ */
+typedef void FNSTAMR3CALLBACKPRINT(PVM pVM, void *pvSample, char *pszBuf, size_t cchBuf);
+/** Pointer to a STAM sample print callback. */
+typedef FNSTAMR3CALLBACKPRINT *PFNSTAMR3CALLBACKPRINT;
+
+VMMR3DECL(int) STAMR3RegisterCallback(PVM pVM, void *pvSample, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint,
+ const char *pszDesc, const char *pszName, ...);
+VMMR3DECL(int) STAMR3RegisterCallbackV(PVM pVM, void *pvSample, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
+ PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint,
+ const char *pszDesc, const char *pszName, va_list args);
+VMMR3DECL(int) STAMR3DeregisterU(PUVM pUVM, void *pvSample);
+VMMR3DECL(int) STAMR3Deregister(PVM pVM, void *pvSample);
+
+/** @def STAM_REL_DEREG
+ * Deregisters a statistics sample if statistics are enabled.
+ *
+ * @param pVM VM Handle.
+ * @param pvSample Pointer to the sample.
+ */
+#define STAM_REL_DEREG(pVM, pvSample) \
+ STAM_REL_STATS({ int rcStam = STAMR3Deregister(pVM, pvSample); AssertRC(rcStam); })
+/** @def STAM_DEREG
+ * Deregisters a statistics sample if statistics are enabled.
+ *
+ * @param pVM VM Handle.
+ * @param pvSample Pointer to the sample.
+ */
+#define STAM_DEREG(pVM, pvSample) \
+ STAM_STATS({ STAM_REL_DEREG(pVM, pvSample); })
+
+VMMR3DECL(int) STAMR3ResetU(PUVM pUVM, const char *pszPat);
+VMMR3DECL(int) STAMR3Reset(PVM pVM, const char *pszPat);
+VMMR3DECL(int) STAMR3SnapshotU(PUVM pUVM, const char *pszPat, char **ppszSnapshot, size_t *pcchSnapshot, bool fWithDesc);
+VMMR3DECL(int) STAMR3Snapshot(PVM pVM, const char *pszPat, char **ppszSnapshot, size_t *pcchSnapshot, bool fWithDesc);
+VMMR3DECL(int) STAMR3SnapshotFreeU(PUVM pUVM, char *pszSnapshot);
+VMMR3DECL(int) STAMR3SnapshotFree(PVM pVM, char *pszSnapshot);
+VMMR3DECL(int) STAMR3DumpU(PUVM pUVM, const char *pszPat);
+VMMR3DECL(int) STAMR3Dump(PVM pVM, const char *pszPat);
+VMMR3DECL(int) STAMR3DumpToReleaseLogU(PUVM pUVM, const char *pszPat);
+VMMR3DECL(int) STAMR3DumpToReleaseLog(PVM pVM, const char *pszPat);
+VMMR3DECL(int) STAMR3PrintU(PUVM pUVM, const char *pszPat);
+VMMR3DECL(int) STAMR3Print(PVM pVM, const char *pszPat);
+
+/**
+ * Callback function for STAMR3Enum().
+ *
+ * @returns non-zero to halt the enumeration.
+ *
+ * @param pszName The name of the sample.
+ * @param enmType The type.
+ * @param pvSample Pointer to the data. enmType indicates the format of this data.
+ * @param enmUnit The unit.
+ * @param enmVisibility The visibility.
+ * @param pszDesc The description.
+ * @param pvUser The pvUser argument given to STAMR3Enum().
+ */
+typedef DECLCALLBACK(int) FNSTAMR3ENUM(const char *pszName, STAMTYPE enmType, void *pvSample, STAMUNIT enmUnit,
+ STAMVISIBILITY enmVisiblity, const char *pszDesc, void *pvUser);
+/** Pointer to a FNSTAMR3ENUM(). */
+typedef FNSTAMR3ENUM *PFNSTAMR3ENUM;
+
+VMMR3DECL(int) STAMR3EnumU(PUVM pUVM, const char *pszPat, PFNSTAMR3ENUM pfnEnum, void *pvUser);
+VMMR3DECL(int) STAMR3Enum(PVM pVM, const char *pszPat, PFNSTAMR3ENUM pfnEnum, void *pvUser);
+VMMR3DECL(const char *) STAMR3GetUnit(STAMUNIT enmUnit);
+
+/** @} */
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/stam.mac b/include/VBox/vmm/stam.mac
new file mode 100644
index 00000000..5e0fd65b
--- /dev/null
+++ b/include/VBox/vmm/stam.mac
@@ -0,0 +1,382 @@
+;; @file
+; STAM - Statistics Manager.
+;
+
+;
+; Copyright (C) 2006-2010 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; 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.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+; VirtualBox OSE distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+
+%ifndef ___VBox_vmm_stam_mac__
+%define ___VBox_vmm_stam_mac__
+
+
+%ifndef VBOX_WITH_STATISTICS
+ %ifdef DEBUG
+ %define VBOX_WITH_STATISTICS
+ %endif
+%endif
+
+
+
+;;
+; Counter sample - STAMTYPE_COUNTER.
+struc STAMCOUNTER
+ .c resd 2
+endstruc
+
+;;
+; Increments a counter sample by one.
+; @param %1 Pointer to the STAMCOUNTER structure to operate on.
+%macro STAM32_COUNTER_INC 1
+%ifdef VBOX_WITH_STATISTICS
+ push ebx
+ mov ebx, %1
+ inc dword [ebx + STAMCOUNTER.c]
+ adc dword [ebx + STAMCOUNTER.c + 1], byte 0
+ pop ebx
+%endif
+%endmacro
+
+%macro STAM64_COUNTER_INC 1
+%ifdef VBOX_WITH_STATISTICS
+ push rbx
+ mov rbx, %1
+ inc qword [rbx + STAMCOUNTER.c]
+ pop rbx
+%endif
+%endmacro
+
+%macro STAM_COUNTER_INC 1
+%ifdef VBOX_WITH_STATISTICS
+ %ifdef RT_ARCH_AMD64
+ STAM64_COUNTER_INC %1
+ %else
+ STAM32_COUNTER_INC %1
+ %endif
+%endif
+%endmacro
+
+
+;;
+; Increments a counter sample by a value.
+;
+; @param %1 Pointer to the STAMCOUNTER structure to operate on.
+; @param %2 The value to add to the counter.
+%macro STAM32_COUNTER_ADD 2
+%ifdef VBOX_WITH_STATISTICS
+ push ebx
+ mov ebx, %1
+ push eax
+ mov eax, %2
+
+ add [ebx + STAMCOUNTER.c], eax
+ adc dword [ebx + STAMCOUNTER.c], byte 0
+
+ pop eax
+ pop ebx
+%endif
+%endmacro
+
+%macro STAM64_COUNTER_ADD 2
+%ifdef VBOX_WITH_STATISTICS
+ push rbx
+ mov rbx, %1
+ push rax
+ mov rax, %2
+
+ add [rbx + STAMCOUNTER.c], rax
+
+ pop rax
+ pop rbx
+%endif
+%endmacro
+
+%macro STAM_COUNTER_ADD 2
+%ifdef VBOX_WITH_STATISTICS
+ %ifdef RT_ARCH_AMD64
+ STAM64_COUNTER_ADD %1, %2
+ %else
+ STAM32_COUNTER_ADD %1, %2
+ %endif
+%endif
+%endmacro
+
+
+;;
+; Profiling sample - STAMTYPE_PROFILE.
+struc STAMPROFILE
+ .cPeriods resd 2
+ .cTicks resd 2
+ .cTicksMax resd 2
+ .cTicksMin resd 2
+endstruc
+
+
+;;
+; Samples the start time of a profiling period.
+;
+; @param %1 Pointer to somewhere one can store a 64-bit timestamp until STAM_PROFILE_STOPP
+%macro STAM32_PROFILE_START 1
+%ifdef VBOX_WITH_STATISTICS
+ push ebx
+ mov ebx, %1
+ push eax
+ push edx
+
+ rdtsc
+ mov [ebx], eax
+ mov [ebx + 4], edx
+
+ pop edx
+ pop eax
+ pop ebx
+%endif
+%endmacro
+
+%macro STAM64_PROFILE_START 1
+%ifdef VBOX_WITH_STATISTICS
+ push rbx
+ mov rbx, %1
+ push rax
+ push rdx
+
+ rdtsc
+ mov [rbx], eax
+ mov [rbx + 4], edx
+
+ pop rdx
+ pop rax
+ pop rbx
+%endif
+%endmacro
+
+%macro STAM_PROFILE_START 1
+%ifdef VBOX_WITH_STATISTICS
+ %ifdef RT_ARCH_AMD64
+ STAM64_PROFILE_START %1
+ %else
+ STAM32_PROFILE_START %1
+ %endif
+%endif
+%endmacro
+
+
+;;
+; Samples the stop time of a profiling period and updates the sample.
+;
+; @param %1 Pointer to the STAMPROFILE structure to operate on.
+; @param %2 Pointer to where the 64-bit timestamp from STAM_PROFILE_START was stored.
+%macro STAM32_PROFILE_STOP 2
+%ifdef VBOX_WITH_STATISTICS
+ push ebx
+ mov ebx, %1
+ push eax
+ push edx
+
+ ; calc cTicks
+ push ecx
+ mov ecx, %2
+ rdtsc
+ sub eax, [ecx]
+ sbb edx, [ecx + 4]
+ pop ecx
+
+ ; update STAMPROFILE.cTicks
+ add [ebx + STAMPROFILE.cTicks], eax
+ adc [ebx + STAMPROFILE.cTicks + 4], edx
+ ; update STAMPROFILE.cPeriods
+ inc dword [ebx + STAMPROFILE.cPeriods]
+ adc dword [ebx + STAMPROFILE.cPeriods + 4], byte 0
+
+ ; update max?
+ cmp edx, [ebx + STAMPROFILE.cTicksMax + 4]
+ jb short %%not_update_max
+ ja short %%update_max
+ cmp eax, [ebx + STAMPROFILE.cTicksMax]
+ jbe short %%not_update_max
+%%update_max:
+ mov [ebx + STAMPROFILE.cTicksMax], eax
+ mov [ebx + STAMPROFILE.cTicksMax + 4], edx
+%%not_update_max:
+
+ ; update min?
+ cmp edx, [ebx + STAMPROFILE.cTicksMin + 4]
+ ja short %%not_update_min
+ jb short %%update_min
+ cmp eax, [ebx + STAMPROFILE.cTicksMin]
+ jae short %%not_update_min
+%%update_min:
+ mov [ebx + STAMPROFILE.cTicksMin], eax
+ mov [ebx + STAMPROFILE.cTicksMin + 4], edx
+%%not_update_min:
+
+ pop edx
+ pop eax
+ pop ebx
+%endif
+%endmacro
+
+%macro STAM64_PROFILE_STOP 2
+%ifdef VBOX_WITH_STATISTICS
+ push rbx
+ mov rbx, %1
+ push rax
+ push rdx
+
+ ; calc cTicks
+ push rcx
+ mov rcx, %2
+ rdtsc
+ sub rax, [ecx]
+ sbb rdx, [ecx + 4]
+ pop rcx
+
+ ; update STAMPROFILE.cTicks
+ shl rdx, 32
+ or rdx, rax
+ add [rbx + STAMPROFILE.cTicks], rdx
+ ; update STAMPROFILE.cPeriods
+ inc qword [rbx + STAMPROFILE.cPeriods]
+
+ ; update max?
+ cmp rdx, [rbx + STAMPROFILE.cTicksMax]
+ jbe short %%not_update_max
+ mov [rbx + STAMPROFILE.cTicksMax], rdx
+%%not_update_max:
+
+ ; update min?
+ cmp rdx, [rbx + STAMPROFILE.cTicksMin]
+ jae short %%not_update_min
+ mov [rbx + STAMPROFILE.cTicksMin], rax
+%%not_update_min:
+
+ pop rdx
+ pop rax
+ pop rbx
+%endif
+%endmacro
+
+%macro STAM_PROFILE_STOP 2
+%ifdef VBOX_WITH_STATISTICS
+ %ifdef RT_ARCH_AMD64
+ STAM64_PROFILE_STOP %1, %2
+ %else
+ STAM32_PROFILE_STOP %1, %2
+ %endif
+%endif
+%endmacro
+
+
+
+struc STAMPROFILEADV
+ .cPeriods resd 2
+ .cTicks resd 2
+ .cTicksMax resd 2
+ .cTicksMin resd 2
+ .tsStart resd 2
+endstruc
+
+
+;;
+; Samples the start time of a profiling period.
+;
+; @param %1 Pointer to the STAMPROFILEADV structure to operate on.
+%macro STAM32_PROFILE_ADV_START 1
+%ifdef VBOX_WITH_STATISTICS
+ push ecx
+ mov ecx, %1
+ lea ecx, [ecx + STAMPROFILEADV.tsStart]
+ STAM32_PROFILE_START ecx
+ pop ecx
+%endif
+%endmacro
+
+%macro STAM64_PROFILE_ADV_START 1
+%ifdef VBOX_WITH_STATISTICS
+ push rcx
+ mov rcx, %1
+ lea rcx, [rcx + STAMPROFILEADV.tsStart]
+ STAM64_PROFILE_START rcx
+ pop rcx
+%endif
+%endmacro
+
+%macro STAM_PROFILE_ADV_START 1
+%ifdef VBOX_WITH_STATISTICS
+ %ifdef RT_ARCH_AMD64
+ STAM64_PROFILE_ADV_START %1
+ %else
+ STAM32_PROFILE_ADV_START %1
+ %endif
+%endif
+%endmacro
+
+
+;;
+; Samples the stop time of a profiling period and updates the sample.
+;
+; @param %1 Pointer to the STAMPROFILEADV structure to operate on.
+
+%macro STAM32_PROFILE_ADV_STOP 1
+%ifdef VBOX_WITH_STATISTICS
+ push ecx
+ mov ecx, %1
+ lea ecx, [ecx + STAMPROFILEADV.tsStart]
+ cmp dword [ecx], byte 0
+ jnz short %%doit
+ cmp dword [ecx + 4], byte 0
+ jz short %%dont
+%%doit:
+ STAM32_PROFILE_STOP %1, ecx
+%%dont:
+ mov dword [ecx], 0
+ mov dword [ecx + 4], 0
+ pop ecx
+%endif
+%endmacro
+
+%macro STAM64_PROFILE_ADV_STOP 1
+%ifdef VBOX_WITH_STATISTICS
+ push rcx
+ mov rcx, %1
+ lea rcx, [rcx + STAMPROFILEADV.tsStart]
+ cmp qword [rcx], byte 0
+ jz short %%dont
+%%doit:
+ STAM64_PROFILE_STOP %1, rcx
+%%dont:
+ mov qword [rcx], 0
+ pop rcx
+%endif
+%endmacro
+
+%macro STAM_PROFILE_ADV_STOP 1
+%ifdef VBOX_WITH_STATISTICS
+ %ifdef RT_ARCH_AMD64
+ STAM64_PROFILE_ADV_STOP %1
+ %else
+ STAM32_PROFILE_ADV_STOP %1
+ %endif
+%endif
+%endmacro
+
+
+
+%endif
diff --git a/include/VBox/vmm/tm.h b/include/VBox/vmm/tm.h
new file mode 100644
index 00000000..be328b1c
--- /dev/null
+++ b/include/VBox/vmm/tm.h
@@ -0,0 +1,281 @@
+/** @file
+ * TM - Time Manager.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_tm_h
+#define ___VBox_vmm_tm_h
+
+#include <VBox/types.h>
+#ifdef IN_RING3
+# include <iprt/time.h>
+#endif
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_tm The Time Manager API
+ * @{
+ */
+
+/** Enable a timer hack which improves the timer response/resolution a bit. */
+#define VBOX_HIGH_RES_TIMERS_HACK
+
+
+/**
+ * Clock type.
+ */
+typedef enum TMCLOCK
+{
+ /** Real host time.
+ * This clock ticks all the time, so use with care. */
+ TMCLOCK_REAL = 0,
+ /** Virtual guest time.
+ * This clock only ticks when the guest is running. It's implemented
+ * as an offset to monotonic real time (GIP). */
+ TMCLOCK_VIRTUAL,
+ /** Virtual guest synchronized timer time.
+ * This is a special clock and timer queue for synchronizing virtual timers
+ * and virtual time sources. This clock is trying to keep up with
+ * TMCLOCK_VIRTUAL, but will wait for timers to be executed. If it lags
+ * too far behind TMCLOCK_VIRTUAL, it will try speed up to close the
+ * distance.
+ * @remarks Do not use this unless you really *must*. */
+ TMCLOCK_VIRTUAL_SYNC,
+ /** Virtual CPU timestamp.
+ * By default this is a function of TMCLOCK_VIRTUAL_SYNC and the virtual
+ * CPU frequency. */
+ TMCLOCK_TSC,
+ /** Number of clocks. */
+ TMCLOCK_MAX
+} TMCLOCK;
+
+
+/** @defgroup grp_tm_timer_flags Timer flags.
+ * @{ */
+/** Use the default critical section for the class of timers. */
+#define TMTIMER_FLAGS_DEFAULT_CRIT_SECT 0
+/** No critical section needed or a custom one is set using
+ * TMR3TimerSetCritSect(). */
+#define TMTIMER_FLAGS_NO_CRIT_SECT RT_BIT_32(0)
+/** @} */
+
+
+VMMDECL(void) TMNotifyStartOfExecution(PVMCPU pVCpu);
+VMMDECL(void) TMNotifyEndOfExecution(PVMCPU pVCpu);
+VMM_INT_DECL(void) TMNotifyStartOfHalt(PVMCPU pVCpu);
+VMM_INT_DECL(void) TMNotifyEndOfHalt(PVMCPU pVCpu);
+#ifdef IN_RING3
+VMMR3DECL(int) TMR3NotifySuspend(PVM pVM, PVMCPU pVCpu);
+VMMR3DECL(int) TMR3NotifyResume(PVM pVM, PVMCPU pVCpu);
+VMMR3DECL(int) TMR3SetWarpDrive(PVM pVM, uint32_t u32Percent);
+#endif
+VMMDECL(uint32_t) TMGetWarpDrive(PVM pVM);
+VMM_INT_DECL(uint32_t) TMCalcHostTimerFrequency(PVM pVM, PVMCPU pVCpu);
+#ifdef IN_RING3
+VMMR3DECL(int) TMR3GetCpuLoadTimes(PVM pVM, VMCPUID idCpu, uint64_t *pcNsTotal, uint64_t *pcNsExecuting,
+ uint64_t *pcNsHalted, uint64_t *pcNsOther);
+#endif
+
+
+/** @name Real Clock Methods
+ * @{
+ */
+VMM_INT_DECL(uint64_t) TMRealGet(PVM pVM);
+VMM_INT_DECL(uint64_t) TMRealGetFreq(PVM pVM);
+/** @} */
+
+
+/** @name Virtual Clock Methods
+ * @{
+ */
+VMM_INT_DECL(uint64_t) TMVirtualGet(PVM pVM);
+VMM_INT_DECL(uint64_t) TMVirtualGetNoCheck(PVM pVM);
+VMM_INT_DECL(uint64_t) TMVirtualSyncGetLag(PVM pVM);
+VMM_INT_DECL(uint32_t) TMVirtualSyncGetCatchUpPct(PVM pVM);
+VMM_INT_DECL(uint64_t) TMVirtualGetFreq(PVM pVM);
+VMM_INT_DECL(uint64_t) TMVirtualSyncGet(PVM pVM);
+VMM_INT_DECL(uint64_t) TMVirtualSyncGetNoCheck(PVM pVM);
+VMM_INT_DECL(uint64_t) TMVirtualSyncGetEx(PVM pVM, bool fCheckTimers);
+VMM_INT_DECL(uint64_t) TMVirtualSyncGetWithDeadlineNoCheck(PVM pVM, uint64_t *pcNsToDeadline);
+VMM_INT_DECL(uint64_t) TMVirtualSyncGetNsToDeadline(PVM pVM);
+VMM_INT_DECL(uint64_t) TMVirtualToNano(PVM pVM, uint64_t u64VirtualTicks);
+VMM_INT_DECL(uint64_t) TMVirtualToMicro(PVM pVM, uint64_t u64VirtualTicks);
+VMM_INT_DECL(uint64_t) TMVirtualToMilli(PVM pVM, uint64_t u64VirtualTicks);
+VMM_INT_DECL(uint64_t) TMVirtualFromNano(PVM pVM, uint64_t u64NanoTS);
+VMM_INT_DECL(uint64_t) TMVirtualFromMicro(PVM pVM, uint64_t u64MicroTS);
+VMM_INT_DECL(uint64_t) TMVirtualFromMilli(PVM pVM, uint64_t u64MilliTS);
+/** @} */
+
+
+/** @name CPU Clock Methods
+ * @{
+ */
+VMMDECL(uint64_t) TMCpuTickGet(PVMCPU pVCpu);
+VMM_INT_DECL(uint64_t) TMCpuTickGetNoCheck(PVMCPU pVCpu);
+VMM_INT_DECL(bool) TMCpuTickCanUseRealTSC(PVMCPU pVCpu, uint64_t *poffRealTSC);
+VMM_INT_DECL(uint64_t) TMCpuTickGetDeadlineAndTscOffset(PVMCPU pVCpu, bool *pfOffsettedTsc, uint64_t *poffRealTSC);
+VMM_INT_DECL(int) TMCpuTickSet(PVM pVM, PVMCPU pVCpu, uint64_t u64Tick);
+VMM_INT_DECL(int) TMCpuTickSetLastSeen(PVMCPU pVCpu, uint64_t u64LastSeenTick);
+VMM_INT_DECL(uint64_t) TMCpuTickGetLastSeen(PVMCPU pVCpu);
+VMMDECL(uint64_t) TMCpuTicksPerSecond(PVM pVM);
+/** @} */
+
+
+/** @name Timer Methods
+ * @{
+ */
+/**
+ * Device timer callback function.
+ *
+ * @param pDevIns Device instance of the device which registered the timer.
+ * @param pTimer The timer handle.
+ * @param pvUser User argument specified upon timer creation.
+ */
+typedef DECLCALLBACK(void) FNTMTIMERDEV(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
+/** Pointer to a device timer callback function. */
+typedef FNTMTIMERDEV *PFNTMTIMERDEV;
+
+/**
+ * USB device timer callback function.
+ *
+ * @param pUsbIns The USB device instance the timer is associated
+ * with.
+ * @param pTimer The timer handle.
+ * @param pvUser User argument specified upon timer creation.
+ */
+typedef DECLCALLBACK(void) FNTMTIMERUSB(PPDMUSBINS pUsbIns, PTMTIMER pTimer, void *pvUser);
+/** Pointer to a timer callback for a USB device. */
+typedef FNTMTIMERUSB *PFNTMTIMERUSB;
+
+/**
+ * Driver timer callback function.
+ *
+ * @param pDrvIns Device instance of the device which registered the timer.
+ * @param pTimer The timer handle.
+ * @param pvUser User argument specified upon timer creation.
+ */
+typedef DECLCALLBACK(void) FNTMTIMERDRV(PPDMDRVINS pDrvIns, PTMTIMER pTimer, void *pvUser);
+/** Pointer to a driver timer callback function. */
+typedef FNTMTIMERDRV *PFNTMTIMERDRV;
+
+/**
+ * Service timer callback function.
+ *
+ * @param pSrvIns Service instance of the device which registered the timer.
+ * @param pTimer The timer handle.
+ */
+typedef DECLCALLBACK(void) FNTMTIMERSRV(PPDMSRVINS pSrvIns, PTMTIMER pTimer);
+/** Pointer to a service timer callback function. */
+typedef FNTMTIMERSRV *PFNTMTIMERSRV;
+
+/**
+ * Internal timer callback function.
+ *
+ * @param pVM The VM.
+ * @param pTimer The timer handle.
+ * @param pvUser User argument specified upon timer creation.
+ */
+typedef DECLCALLBACK(void) FNTMTIMERINT(PVM pVM, PTMTIMER pTimer, void *pvUser);
+/** Pointer to internal timer callback function. */
+typedef FNTMTIMERINT *PFNTMTIMERINT;
+
+/**
+ * External timer callback function.
+ *
+ * @param pvUser User argument as specified when the timer was created.
+ */
+typedef DECLCALLBACK(void) FNTMTIMEREXT(void *pvUser);
+/** Pointer to an external timer callback function. */
+typedef FNTMTIMEREXT *PFNTMTIMEREXT;
+
+VMMDECL(PTMTIMERR3) TMTimerR3Ptr(PTMTIMER pTimer);
+VMMDECL(PTMTIMERR0) TMTimerR0Ptr(PTMTIMER pTimer);
+VMMDECL(PTMTIMERRC) TMTimerRCPtr(PTMTIMER pTimer);
+VMMDECL(int) TMTimerLock(PTMTIMER pTimer, int rcBusy);
+VMMDECL(void) TMTimerUnlock(PTMTIMER pTimer);
+VMMDECL(bool) TMTimerIsLockOwner(PTMTIMER pTimer);
+VMMDECL(int) TMTimerSet(PTMTIMER pTimer, uint64_t u64Expire);
+VMMDECL(int) TMTimerSetRelative(PTMTIMER pTimer, uint64_t cTicksToNext, uint64_t *pu64Now);
+VMMDECL(int) TMTimerSetFrequencyHint(PTMTIMER pTimer, uint32_t uHz);
+VMMDECL(uint64_t) TMTimerGet(PTMTIMER pTimer);
+VMMDECL(int) TMTimerStop(PTMTIMER pTimer);
+VMMDECL(bool) TMTimerIsActive(PTMTIMER pTimer);
+
+VMMDECL(int) TMTimerSetMillies(PTMTIMER pTimer, uint32_t cMilliesToNext);
+VMMDECL(int) TMTimerSetMicro(PTMTIMER pTimer, uint64_t cMicrosToNext);
+VMMDECL(int) TMTimerSetNano(PTMTIMER pTimer, uint64_t cNanosToNext);
+VMMDECL(uint64_t) TMTimerGetNano(PTMTIMER pTimer);
+VMMDECL(uint64_t) TMTimerGetMicro(PTMTIMER pTimer);
+VMMDECL(uint64_t) TMTimerGetMilli(PTMTIMER pTimer);
+VMMDECL(uint64_t) TMTimerGetFreq(PTMTIMER pTimer);
+VMMDECL(uint64_t) TMTimerGetExpire(PTMTIMER pTimer);
+VMMDECL(uint64_t) TMTimerToNano(PTMTIMER pTimer, uint64_t cTicks);
+VMMDECL(uint64_t) TMTimerToMicro(PTMTIMER pTimer, uint64_t cTicks);
+VMMDECL(uint64_t) TMTimerToMilli(PTMTIMER pTimer, uint64_t cTicks);
+VMMDECL(uint64_t) TMTimerFromNano(PTMTIMER pTimer, uint64_t cNanoSecs);
+VMMDECL(uint64_t) TMTimerFromMicro(PTMTIMER pTimer, uint64_t cMicroSecs);
+VMMDECL(uint64_t) TMTimerFromMilli(PTMTIMER pTimer, uint64_t cMilliSecs);
+
+VMMDECL(bool) TMTimerPollBool(PVM pVM, PVMCPU pVCpu);
+VMM_INT_DECL(void) TMTimerPollVoid(PVM pVM, PVMCPU pVCpu);
+VMM_INT_DECL(uint64_t) TMTimerPollGIP(PVM pVM, PVMCPU pVCpu, uint64_t *pu64Delta);
+
+/** @} */
+
+
+#ifdef IN_RING3
+/** @defgroup grp_tm_r3 The TM Host Context Ring-3 API
+ * @ingroup grp_tm
+ * @{
+ */
+VMM_INT_DECL(int) TMR3Init(PVM pVM);
+VMM_INT_DECL(int) TMR3InitFinalize(PVM pVM);
+VMM_INT_DECL(void) TMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMM_INT_DECL(int) TMR3Term(PVM pVM);
+VMM_INT_DECL(void) TMR3Reset(PVM pVM);
+VMM_INT_DECL(int) TMR3GetImportRC(PVM pVM, const char *pszSymbol, PRTRCPTR pRCPtrValue);
+VMM_INT_DECL(int) TMR3TimerCreateDevice(PVM pVM, PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, void *pvUser, uint32_t fFlags, const char *pszDesc, PPTMTIMERR3 ppTimer);
+VMM_INT_DECL(int) TMR3TimerCreateUsb(PVM pVM, PPDMUSBINS pUsbIns, TMCLOCK enmClock, PFNTMTIMERUSB pfnCallback, void *pvUser, uint32_t fFlags, const char *pszDesc, PPTMTIMERR3 ppTimer);
+VMM_INT_DECL(int) TMR3TimerCreateDriver(PVM pVM, PPDMDRVINS pDrvIns, TMCLOCK enmClock, PFNTMTIMERDRV pfnCallback, void *pvUser, uint32_t fFlags, const char *pszDesc, PPTMTIMERR3 ppTimer);
+VMMR3DECL(int) TMR3TimerCreateInternal(PVM pVM, TMCLOCK enmClock, PFNTMTIMERINT pfnCallback, void *pvUser, const char *pszDesc, PPTMTIMERR3 ppTimer);
+VMMR3DECL(PTMTIMERR3) TMR3TimerCreateExternal(PVM pVM, TMCLOCK enmClock, PFNTMTIMEREXT pfnCallback, void *pvUser, const char *pszDesc);
+VMMR3DECL(int) TMR3TimerDestroy(PTMTIMER pTimer);
+VMM_INT_DECL(int) TMR3TimerDestroyDevice(PVM pVM, PPDMDEVINS pDevIns);
+VMM_INT_DECL(int) TMR3TimerDestroyUsb(PVM pVM, PPDMUSBINS pUsbIns);
+VMM_INT_DECL(int) TMR3TimerDestroyDriver(PVM pVM, PPDMDRVINS pDrvIns);
+VMMR3DECL(int) TMR3TimerSave(PTMTIMERR3 pTimer, PSSMHANDLE pSSM);
+VMMR3DECL(int) TMR3TimerLoad(PTMTIMERR3 pTimer, PSSMHANDLE pSSM);
+VMMR3DECL(int) TMR3TimerSetCritSect(PTMTIMERR3 pTimer, PPDMCRITSECT pCritSect);
+VMMR3DECL(void) TMR3TimerQueuesDo(PVM pVM);
+VMMR3_INT_DECL(void) TMR3VirtualSyncFF(PVM pVM, PVMCPU pVCpu);
+VMMR3_INT_DECL(PRTTIMESPEC) TMR3UtcNow(PVM pVM, PRTTIMESPEC pTime);
+/** @} */
+#endif /* IN_RING3 */
+
+
+/** @} */
+
+RT_C_DECLS_END
+
+#endif
+
diff --git a/include/VBox/vmm/trpm.h b/include/VBox/vmm/trpm.h
new file mode 100644
index 00000000..0cdfc153
--- /dev/null
+++ b/include/VBox/vmm/trpm.h
@@ -0,0 +1,150 @@
+/** @file
+ * TRPM - The Trap Monitor.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_trpm_h
+#define ___VBox_vmm_trpm_h
+
+#include <VBox/types.h>
+#include <iprt/x86.h>
+
+
+RT_C_DECLS_BEGIN
+/** @defgroup grp_trpm The Trap Monitor API
+ * @{
+ */
+
+/**
+ * Trap: error code present or not
+ */
+typedef enum
+{
+ TRPM_TRAP_HAS_ERRORCODE = 0,
+ TRPM_TRAP_NO_ERRORCODE,
+ /** The usual 32-bit paranoia. */
+ TRPM_TRAP_32BIT_HACK = 0x7fffffff
+} TRPMERRORCODE;
+
+/**
+ * TRPM event type
+ */
+/** Note: must match trpm.mac! */
+typedef enum
+{
+ TRPM_TRAP = 0,
+ TRPM_HARDWARE_INT = 1,
+ TRPM_SOFTWARE_INT = 2,
+ /** The usual 32-bit paranoia. */
+ TRPM_32BIT_HACK = 0x7fffffff
+} TRPMEVENT;
+/** Pointer to a TRPM event type. */
+typedef TRPMEVENT *PTRPMEVENT;
+/** Pointer to a const TRPM event type. */
+typedef TRPMEVENT const *PCTRPMEVENT;
+
+/**
+ * Invalid trap handler for trampoline calls
+ */
+#define TRPM_INVALID_HANDLER 0
+
+VMMDECL(int) TRPMQueryTrap(PVMCPU pVCpu, uint8_t *pu8TrapNo, PTRPMEVENT pEnmType);
+VMMDECL(uint8_t) TRPMGetTrapNo(PVMCPU pVCpu);
+VMMDECL(RTGCUINT) TRPMGetErrorCode(PVMCPU pVCpu);
+VMMDECL(RTGCUINTPTR) TRPMGetFaultAddress(PVMCPU pVCpu);
+VMMDECL(int) TRPMResetTrap(PVMCPU pVCpu);
+VMMDECL(int) TRPMAssertTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType);
+VMMDECL(void) TRPMSetErrorCode(PVMCPU pVCpu, RTGCUINT uErrorCode);
+VMMDECL(void) TRPMSetFaultAddress(PVMCPU pVCpu, RTGCUINTPTR uCR2);
+VMMDECL(bool) TRPMIsSoftwareInterrupt(PVMCPU pVCpu);
+VMMDECL(bool) TRPMHasTrap(PVMCPU pVCpu);
+VMMDECL(int) TRPMQueryTrapAll(PVMCPU pVCpu, uint8_t *pu8TrapNo, PTRPMEVENT pEnmType, PRTGCUINT puErrorCode, PRTGCUINTPTR puCR2);
+VMMDECL(void) TRPMSaveTrap(PVMCPU pVCpu);
+VMMDECL(void) TRPMRestoreTrap(PVMCPU pVCpu);
+VMMDECL(int) TRPMForwardTrap(PVMCPU pVCpu, PCPUMCTXCORE pRegFrame, uint32_t iGate, uint32_t cbInstr, TRPMERRORCODE enmError, TRPMEVENT enmType, int32_t iOrgTrap);
+VMMDECL(int) TRPMRaiseXcpt(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, X86XCPT enmXcpt);
+VMMDECL(int) TRPMRaiseXcptErr(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, X86XCPT enmXcpt, uint32_t uErr);
+VMMDECL(int) TRPMRaiseXcptErrCR2(PVMCPU pVCpu, PCPUMCTXCORE pCtxCore, X86XCPT enmXcpt, uint32_t uErr, RTGCUINTPTR uCR2);
+
+
+#ifdef IN_RING3
+/** @defgroup grp_trpm_r3 TRPM Host Context Ring 3 API
+ * @ingroup grp_trpm
+ * @{
+ */
+VMMR3DECL(int) TRPMR3Init(PVM pVM);
+VMMR3DECL(void) TRPMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3DECL(void) TRPMR3ResetCpu(PVMCPU pVCpu);
+VMMR3DECL(void) TRPMR3Reset(PVM pVM);
+VMMR3_INT_DECL(int) TRPMR3GetImportRC(PVM pVM, const char *pszSymbol, PRTRCPTR pRCPtrValue);
+VMMR3DECL(int) TRPMR3Term(PVM pVM);
+VMMR3DECL(int) TRPMR3EnableGuestTrapHandler(PVM pVM, unsigned iTrap);
+VMMR3DECL(int) TRPMR3SetGuestTrapHandler(PVM pVM, unsigned iTrap, RTRCPTR pHandler);
+VMMR3DECL(RTRCPTR) TRPMR3GetGuestTrapHandler(PVM pVM, unsigned iTrap);
+VMMR3DECL(void) TRPMR3DisableMonitoring(PVM pVM);
+VMMR3DECL(int) TRPMR3SyncIDT(PVM pVM, PVMCPU pVCpu);
+VMMR3DECL(bool) TRPMR3IsGateHandler(PVM pVM, RTRCPTR GCPtr);
+VMMR3DECL(uint32_t) TRPMR3QueryGateByHandler(PVM pVM, RTRCPTR GCPtr);
+VMMR3DECL(int) TRPMR3InjectEvent(PVM pVM, PVMCPU pVCpu, TRPMEVENT enmEvent);
+/** @} */
+#endif
+
+
+#ifdef IN_RC
+/** @defgroup grp_trpm_gc The TRPM Guest Context API
+ * @ingroup grp_trpm
+ * @{
+ */
+
+/**
+ * Guest Context temporary trap handler
+ *
+ * @returns VBox status code (appropriate for GC return).
+ * In this context VINF_SUCCESS means to restart the instruction.
+ * @param pVM VM handle.
+ * @param pRegFrame Trap register frame.
+ */
+typedef DECLCALLBACK(int) FNTRPMGCTRAPHANDLER(PVM pVM, PCPUMCTXCORE pRegFrame);
+/** Pointer to a TRPMGCTRAPHANDLER() function. */
+typedef FNTRPMGCTRAPHANDLER *PFNTRPMGCTRAPHANDLER;
+
+VMMRCDECL(int) TRPMGCSetTempHandler(PVM pVM, unsigned iTrap, PFNTRPMGCTRAPHANDLER pfnHandler);
+VMMRCDECL(void) TRPMGCHyperReturnToHost(PVM pVM, int rc);
+/** @} */
+#endif
+
+
+#ifdef IN_RING0
+/** @defgroup grp_trpm_r0 TRPM Host Context Ring 0 API
+ * @ingroup grp_trpm
+ * @{
+ */
+VMMR0DECL(void) TRPMR0DispatchHostInterrupt(PVM pVM);
+VMMR0DECL(void) TRPMR0SetupInterruptDispatcherFrame(PVM pVM, void *pvRet);
+/** @} */
+#endif
+
+/** @} */
+RT_C_DECLS_END
+
+#endif
diff --git a/include/VBox/vmm/trpm.mac b/include/VBox/vmm/trpm.mac
new file mode 100644
index 00000000..534039e2
--- /dev/null
+++ b/include/VBox/vmm/trpm.mac
@@ -0,0 +1,47 @@
+;; @file
+; TRPM - The Trap Monitor.
+;
+
+;
+; Copyright (C) 2006-2010 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; 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.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+; VirtualBox OSE distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+
+%ifndef ___VBox_vmm_trpm_mac__
+%define ___VBox_vmm_trpm_mac__
+
+
+;/**
+; * TRPM event type
+; */
+;/** Note: must match trpm.mac! */
+;typedef enum
+;{
+; TRPM_TRAP = 0,
+; TRPM_HARDWARE_INT = 1,
+; TRPM_SOFTWARE_INT = 2,
+; /** The usual 32-bit paranoia. */
+; TRPM_32BIT_HACK = 0x7fffffff
+;} TRPMEVENT;
+
+%define TRPM_TRAP 0
+%define TRPM_HARDWARE_INT 1
+%define TRPM_SOFTWARE_INT 2
+%endif
+
diff --git a/include/VBox/vmm/uvm.h b/include/VBox/vmm/uvm.h
new file mode 100644
index 00000000..10b8e49b
--- /dev/null
+++ b/include/VBox/vmm/uvm.h
@@ -0,0 +1,152 @@
+/** @file
+ * GVM - The Global VM Data.
+ */
+
+/*
+ * Copyright (C) 2007-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+
+#ifndef ___VBox_vmm_uvm_h
+#define ___VBox_vmm_uvm_h
+
+#include <VBox/types.h>
+#include <iprt/assert.h>
+
+
+/**
+ * Per virtual CPU ring-3 (user mode) data.
+ */
+typedef struct UVMCPU
+{
+ /** Pointer to the UVM structure. */
+ PUVM pUVM;
+ /** Pointer to the VM structure. */
+ PVM pVM;
+ /** Pointer to the VMCPU structure. */
+ PVMCPU pVCpu;
+ /** The virtual CPU ID. */
+ RTCPUID idCpu;
+ /** Alignment padding. */
+ uint8_t abAlignment0[HC_ARCH_BITS == 32 ? 16 : 4];
+
+ /** The VM internal data. */
+ union
+ {
+#ifdef ___VMInternal_h
+ struct VMINTUSERPERVMCPU s;
+#endif
+ uint8_t padding[512];
+ } vm;
+} UVMCPU;
+AssertCompileMemberAlignment(UVMCPU, vm, 32);
+
+
+/**
+ * The ring-3 (user mode) VM structure.
+ *
+ * This structure is similar to VM and GVM except that it resides in swappable
+ * user memory. The main purpose is to assist bootstrapping, where it allows us
+ * to start EMT much earlier and gives PDMLdr somewhere to put it's VMMR0 data.
+ * It is also a nice place to put big things that are user mode only.
+ */
+typedef struct UVM
+{
+ /** Magic / eye-catcher (UVM_MAGIC). */
+ uint32_t u32Magic;
+ /** The number of virtual CPUs. */
+ uint32_t cCpus;
+ /** The ring-3 mapping of the shared VM structure. */
+ PVM pVM;
+ /** Pointer to the next VM.
+ * We keep a per process list of VM for the event that a process could
+ * contain more than one VM.
+ * @todo move this into vm.s!
+ */
+ struct UVM *pNext;
+
+ /** Pointer to the optional method table provided by the VMM user. */
+ PCVMM2USERMETHODS pVmm2UserMethods;
+
+#if HC_ARCH_BITS == 32
+ /** Align the next member on a 32 byte boundary. */
+ uint8_t abAlignment0[HC_ARCH_BITS == 32 ? 12 : 0];
+#endif
+
+ /** The VM internal data. */
+ union
+ {
+#ifdef ___VMInternal_h
+ struct VMINTUSERPERVM s;
+#endif
+ uint8_t padding[512];
+ } vm;
+
+ /** The MM data. */
+ union
+ {
+#ifdef ___MMInternal_h
+ struct MMUSERPERVM s;
+#endif
+ uint8_t padding[32];
+ } mm;
+
+ /** The PDM data. */
+ union
+ {
+#ifdef ___PDMInternal_h
+ struct PDMUSERPERVM s;
+#endif
+ uint8_t padding[128];
+ } pdm;
+
+ /** The STAM data. */
+ union
+ {
+#ifdef ___STAMInternal_h
+ struct STAMUSERPERVM s;
+#endif
+ uint8_t padding[6624];
+ } stam;
+
+ /** Per virtual CPU data. */
+ UVMCPU aCpus[1];
+} UVM;
+AssertCompileMemberAlignment(UVM, vm, 32);
+AssertCompileMemberAlignment(UVM, mm, 32);
+AssertCompileMemberAlignment(UVM, pdm, 32);
+AssertCompileMemberAlignment(UVM, stam, 32);
+AssertCompileMemberAlignment(UVM, aCpus, 32);
+
+/** The UVM::u32Magic value (Brad Mehldau). */
+#define UVM_MAGIC 0x19700823
+
+/** @def UVM_ASSERT_VALID_EXT_RETURN
+ * Asserts a user mode VM handle is valid for external access.
+ */
+#define UVM_ASSERT_VALID_EXT_RETURN(a_pUVM, a_rc) \
+ AssertMsgReturn( RT_VALID_ALIGNED_PTR(a_pUVM, PAGE_SIZE) \
+ && (a_pUVM)->u32Magic == UVM_MAGIC, \
+ ("a_pUVM=%p u32Magic=%#x\n", (a_pUVM), \
+ RT_VALID_ALIGNED_PTR(a_pUVM, PAGE_SIZE) ? (a_pUVM)->u32Magic : 0), \
+ (a_rc))
+
+#endif
+
diff --git a/include/VBox/vmm/vm.h b/include/VBox/vmm/vm.h
new file mode 100644
index 00000000..ef713127
--- /dev/null
+++ b/include/VBox/vmm/vm.h
@@ -0,0 +1,1106 @@
+/** @file
+ * VM - The Virtual Machine, data.
+ */
+
+/*
+ * Copyright (C) 2006-2012 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_vm_h
+#define ___VBox_vmm_vm_h
+
+#ifndef VBOX_FOR_DTRACE_LIB
+# include <VBox/types.h>
+# include <VBox/vmm/cpum.h>
+# include <VBox/vmm/stam.h>
+# include <VBox/vmm/vmapi.h>
+# include <VBox/vmm/vmm.h>
+# include <VBox/sup.h>
+#else
+# pragma D depends_on library vbox-types.d
+# pragma D depends_on library CPUMInternal.d
+# define ___CPUMInternal_h
+#endif
+
+
+
+/** @defgroup grp_vm The Virtual Machine
+ * @{
+ */
+
+/**
+ * The state of a Virtual CPU.
+ *
+ * The basic state indicated here is whether the CPU has been started or not. In
+ * addition, there are sub-states when started for assisting scheduling (GVMM
+ * mostly).
+ *
+ * The transition out of the STOPPED state is done by a vmR3PowerOn.
+ * The transition back to the STOPPED state is done by vmR3PowerOff.
+ *
+ * (Alternatively we could let vmR3PowerOn start CPU 0 only and let the SPIP
+ * handling switch on the other CPUs. Then vmR3Reset would stop all but CPU 0.)
+ */
+typedef enum VMCPUSTATE
+{
+ /** The customary invalid zero. */
+ VMCPUSTATE_INVALID = 0,
+
+ /** Virtual CPU has not yet been started. */
+ VMCPUSTATE_STOPPED,
+
+ /** CPU started. */
+ VMCPUSTATE_STARTED,
+ /** Executing guest code and can be poked. */
+ VMCPUSTATE_STARTED_EXEC,
+ /** Executing guest code in the recompiler. */
+ VMCPUSTATE_STARTED_EXEC_REM,
+ /** Halted. */
+ VMCPUSTATE_STARTED_HALTED,
+
+ /** The end of valid virtual CPU states. */
+ VMCPUSTATE_END,
+
+ /** Ensure 32-bit type. */
+ VMCPUSTATE_32BIT_HACK = 0x7fffffff
+} VMCPUSTATE;
+
+
+/**
+ * Per virtual CPU data.
+ */
+typedef struct VMCPU
+{
+ /** Per CPU forced action.
+ * See the VMCPU_FF_* \#defines. Updated atomically. */
+ uint32_t volatile fLocalForcedActions; /* 0 */
+ /** The CPU state. */
+ VMCPUSTATE volatile enmState; /* 4 */
+
+ /** Pointer to the ring-3 UVMCPU structure. */
+ PUVMCPU pUVCpu; /* 8 */
+ /** Ring-3 Host Context VM Pointer. */
+ PVMR3 pVMR3; /* 16 / 12 */
+ /** Ring-0 Host Context VM Pointer. */
+ PVMR0 pVMR0; /* 24 / 16 */
+ /** Raw-mode Context VM Pointer. */
+ PVMRC pVMRC; /* 32 / 20 */
+ /** The CPU ID.
+ * This is the index into the VM::aCpu array. */
+ VMCPUID idCpu; /* 36 / 24 */
+ /** The native thread handle. */
+ RTNATIVETHREAD hNativeThread; /* 40 / 28 */
+ /** The native R0 thread handle. (different from the R3 handle!) */
+ RTNATIVETHREAD hNativeThreadR0; /* 48 / 32 */
+ /** Which host CPU ID is this EMT running on.
+ * Only valid when in RC or HWACCMR0 with scheduling disabled. */
+ RTCPUID volatile idHostCpu; /* 56 / 36 */
+
+ /** Trace groups enable flags. */
+ uint32_t fTraceGroups; /* 60 / 40 */
+ /** Align the structures below bit on a 64-byte boundary and make sure it starts
+ * at the same offset in both 64-bit and 32-bit builds.
+ *
+ * @remarks The alignments of the members that are larger than 48 bytes should be
+ * 64-byte for cache line reasons. structs containing small amounts of
+ * data could be lumped together at the end with a < 64 byte padding
+ * following it (to grow into and align the struct size).
+ * */
+ uint8_t abAlignment1[HC_ARCH_BITS == 64 ? 60 : 16+64];
+ /** State data for use by ad hoc profiling. */
+ uint32_t uAdHoc;
+ /** Profiling samples for use by ad hoc profiling. */
+ STAMPROFILEADV aStatAdHoc[8]; /* size: 40*8 = 320 */
+
+ /** CPUM part. */
+ union
+ {
+#ifdef ___CPUMInternal_h
+ struct CPUMCPU s;
+#endif
+ uint8_t padding[3584]; /* multiple of 64 */
+ } cpum;
+
+ /** HWACCM part. */
+ union
+ {
+#ifdef ___HWACCMInternal_h
+ struct HWACCMCPU s;
+#endif
+ uint8_t padding[5376]; /* multiple of 64 */
+ } hwaccm;
+
+ /** EM part. */
+ union
+ {
+#ifdef ___EMInternal_h
+ struct EMCPU s;
+#endif
+ uint8_t padding[1472]; /* multiple of 64 */
+ } em;
+
+ /** IEM part. */
+ union
+ {
+#ifdef ___IEMInternal_h
+ struct IEMCPU s;
+#endif
+ uint8_t padding[3072]; /* multiple of 64 */
+ } iem;
+
+ /** TRPM part. */
+ union
+ {
+#ifdef ___TRPMInternal_h
+ struct TRPMCPU s;
+#endif
+ uint8_t padding[128]; /* multiple of 64 */
+ } trpm;
+
+ /** TM part. */
+ union
+ {
+#ifdef ___TMInternal_h
+ struct TMCPU s;
+#endif
+ uint8_t padding[384]; /* multiple of 64 */
+ } tm;
+
+ /** VMM part. */
+ union
+ {
+#ifdef ___VMMInternal_h
+ struct VMMCPU s;
+#endif
+ uint8_t padding[640]; /* multiple of 64 */
+ } vmm;
+
+ /** PDM part. */
+ union
+ {
+#ifdef ___PDMInternal_h
+ struct PDMCPU s;
+#endif
+ uint8_t padding[128]; /* multiple of 64 */
+ } pdm;
+
+ /** IOM part. */
+ union
+ {
+#ifdef ___IOMInternal_h
+ struct IOMCPU s;
+#endif
+ uint8_t padding[512]; /* multiple of 64 */
+ } iom;
+
+ /** DBGF part.
+ * @todo Combine this with other tiny structures. */
+ union
+ {
+#ifdef ___DBGFInternal_h
+ struct DBGFCPU s;
+#endif
+ uint8_t padding[64]; /* multiple of 64 */
+ } dbgf;
+
+ /** Align the following members on page boundary. */
+ uint8_t abAlignment2[1024 - 320 - 128];
+
+ /** PGM part. */
+ union
+ {
+#ifdef ___PGMInternal_h
+ struct PGMCPU s;
+#endif
+ uint8_t padding[4096]; /* multiple of 4096 */
+ } pgm;
+
+} VMCPU;
+
+
+#ifndef VBOX_FOR_DTRACE_LIB
+
+/** @name Operations on VMCPU::enmState
+ * @{ */
+/** Gets the VMCPU state. */
+#define VMCPU_GET_STATE(pVCpu) ( (pVCpu)->enmState )
+/** Sets the VMCPU state. */
+#define VMCPU_SET_STATE(pVCpu, enmNewState) \
+ ASMAtomicWriteU32((uint32_t volatile *)&(pVCpu)->enmState, (enmNewState))
+/** Cmpares and sets the VMCPU state. */
+#define VMCPU_CMPXCHG_STATE(pVCpu, enmNewState, enmOldState) \
+ ASMAtomicCmpXchgU32((uint32_t volatile *)&(pVCpu)->enmState, (enmNewState), (enmOldState))
+/** Checks the VMCPU state. */
+#ifdef VBOX_STRICT
+# define VMCPU_ASSERT_STATE(pVCpu, enmExpectedState) \
+ do { \
+ VMCPUSTATE enmState = VMCPU_GET_STATE(pVCpu); \
+ AssertMsg(enmState == (enmExpectedState), \
+ ("enmState=%d enmExpectedState=%d idCpu=%u\n", \
+ enmState, enmExpectedState, (pVCpu)->idCpu)); \
+ } while (0)
+#else
+# define VMCPU_ASSERT_STATE(pVCpu, enmExpectedState) do { } while (0)
+#endif
+/** Tests if the state means that the CPU is started. */
+#define VMCPUSTATE_IS_STARTED(enmState) ( (enmState) > VMCPUSTATE_STOPPED )
+/** Tests if the state means that the CPU is stopped. */
+#define VMCPUSTATE_IS_STOPPED(enmState) ( (enmState) == VMCPUSTATE_STOPPED )
+/** @} */
+
+
+/** The name of the Guest Context VMM Core module. */
+#define VMMGC_MAIN_MODULE_NAME "VMMGC.gc"
+/** The name of the Ring 0 Context VMM Core module. */
+#define VMMR0_MAIN_MODULE_NAME "VMMR0.r0"
+
+/** VM Forced Action Flags.
+ *
+ * Use the VM_FF_SET() and VM_FF_CLEAR() macros to change the force
+ * action mask of a VM.
+ *
+ * @{
+ */
+/** The virtual sync clock has been stopped, go to TM until it has been
+ * restarted... */
+#define VM_FF_TM_VIRTUAL_SYNC RT_BIT_32(2)
+/** PDM Queues are pending. */
+#define VM_FF_PDM_QUEUES RT_BIT_32(VM_FF_PDM_QUEUES_BIT)
+/** The bit number for VM_FF_PDM_QUEUES. */
+#define VM_FF_PDM_QUEUES_BIT 3
+/** PDM DMA transfers are pending. */
+#define VM_FF_PDM_DMA RT_BIT_32(VM_FF_PDM_DMA_BIT)
+/** The bit number for VM_FF_PDM_DMA. */
+#define VM_FF_PDM_DMA_BIT 4
+/** This action forces the VM to call DBGF so DBGF can service debugger
+ * requests in the emulation thread.
+ * This action flag stays asserted till DBGF clears it.*/
+#define VM_FF_DBGF RT_BIT_32(VM_FF_DBGF_BIT)
+/** The bit number for VM_FF_DBGF. */
+#define VM_FF_DBGF_BIT 8
+/** This action forces the VM to service pending requests from other
+ * thread or requests which must be executed in another context. */
+#define VM_FF_REQUEST RT_BIT_32(9)
+/** Check for VM state changes and take appropriate action. */
+#define VM_FF_CHECK_VM_STATE RT_BIT_32(VM_FF_CHECK_VM_STATE_BIT)
+/** The bit number for VM_FF_CHECK_VM_STATE. */
+#define VM_FF_CHECK_VM_STATE_BIT 10
+/** Reset the VM. (postponed) */
+#define VM_FF_RESET RT_BIT_32(VM_FF_RESET_BIT)
+/** The bit number for VM_FF_RESET. */
+#define VM_FF_RESET_BIT 11
+/** EMT rendezvous in VMM. */
+#define VM_FF_EMT_RENDEZVOUS RT_BIT_32(VM_FF_EMT_RENDEZVOUS_BIT)
+/** The bit number for VM_FF_EMT_RENDEZVOUS. */
+#define VM_FF_EMT_RENDEZVOUS_BIT 12
+
+/** PGM needs to allocate handy pages. */
+#define VM_FF_PGM_NEED_HANDY_PAGES RT_BIT_32(18)
+/** PGM is out of memory.
+ * Abandon all loops and code paths which can be resumed and get up to the EM
+ * loops. */
+#define VM_FF_PGM_NO_MEMORY RT_BIT_32(19)
+ /** PGM is about to perform a lightweight pool flush
+ * Guest SMP: all EMT threads should return to ring 3
+ */
+#define VM_FF_PGM_POOL_FLUSH_PENDING RT_BIT_32(20)
+/** REM needs to be informed about handler changes. */
+#define VM_FF_REM_HANDLER_NOTIFY RT_BIT_32(VM_FF_REM_HANDLER_NOTIFY_BIT)
+/** The bit number for VM_FF_REM_HANDLER_NOTIFY. */
+#define VM_FF_REM_HANDLER_NOTIFY_BIT 29
+/** Suspend the VM - debug only. */
+#define VM_FF_DEBUG_SUSPEND RT_BIT_32(31)
+
+
+/** This action forces the VM to check any pending interrups on the APIC. */
+#define VMCPU_FF_INTERRUPT_APIC RT_BIT_32(0)
+/** This action forces the VM to check any pending interrups on the PIC. */
+#define VMCPU_FF_INTERRUPT_PIC RT_BIT_32(1)
+/** This action forces the VM to schedule and run pending timer (TM).
+ * @remarks Don't move - PATM compatibility. */
+#define VMCPU_FF_TIMER RT_BIT_32(2)
+/** This action forces the VM to check any pending NMIs. */
+#define VMCPU_FF_INTERRUPT_NMI_BIT 3
+#define VMCPU_FF_INTERRUPT_NMI RT_BIT_32(VMCPU_FF_INTERRUPT_NMI_BIT)
+/** This action forces the VM to check any pending SMIs. */
+#define VMCPU_FF_INTERRUPT_SMI_BIT 4
+#define VMCPU_FF_INTERRUPT_SMI RT_BIT_32(VMCPU_FF_INTERRUPT_SMI_BIT)
+/** PDM critical section unlocking is pending, process promptly upon return to R3. */
+#define VMCPU_FF_PDM_CRITSECT RT_BIT_32(5)
+/** This action forces the VM to service pending requests from other
+ * thread or requests which must be executed in another context. */
+#define VMCPU_FF_REQUEST RT_BIT_32(9)
+/** This action forces the VM to resync the page tables before going
+ * back to execute guest code. (GLOBAL FLUSH) */
+#define VMCPU_FF_PGM_SYNC_CR3 RT_BIT_32(16)
+/** Same as VM_FF_PGM_SYNC_CR3 except that global pages can be skipped.
+ * (NON-GLOBAL FLUSH) */
+#define VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL RT_BIT_32(17)
+/** Check for pending TLB shootdown actions.
+ * Consumer: HWACCM
+ * @todo rename to VMCPU_FF_HWACCM_TLB_SHOOTDOWN */
+#define VMCPU_FF_TLB_SHOOTDOWN RT_BIT_32(18)
+/** Check for pending TLB flush action.
+ * Consumer: HWACCM
+ * @todo rename to VMCPU_FF_HWACCM_TLB_FLUSH */
+#define VMCPU_FF_TLB_FLUSH RT_BIT_32(VMCPU_FF_TLB_FLUSH_BIT)
+/** The bit number for VMCPU_FF_TLB_FLUSH. */
+#define VMCPU_FF_TLB_FLUSH_BIT 19
+/** Check the interrupt and trap gates */
+#define VMCPU_FF_TRPM_SYNC_IDT RT_BIT_32(20)
+/** Check Guest's TSS ring 0 stack */
+#define VMCPU_FF_SELM_SYNC_TSS RT_BIT_32(21)
+/** Check Guest's GDT table */
+#define VMCPU_FF_SELM_SYNC_GDT RT_BIT_32(22)
+/** Check Guest's LDT table */
+#define VMCPU_FF_SELM_SYNC_LDT RT_BIT_32(23)
+/** Inhibit interrupts pending. See EMGetInhibitInterruptsPC(). */
+#define VMCPU_FF_INHIBIT_INTERRUPTS RT_BIT_32(24)
+/** CSAM needs to scan the page that's being executed */
+#define VMCPU_FF_CSAM_SCAN_PAGE RT_BIT_32(26)
+/** CSAM needs to do some homework. */
+#define VMCPU_FF_CSAM_PENDING_ACTION RT_BIT_32(27)
+/** Force return to Ring-3. */
+#define VMCPU_FF_TO_R3 RT_BIT_32(28)
+
+/** Externally VM forced actions. Used to quit the idle/wait loop. */
+#define VM_FF_EXTERNAL_SUSPENDED_MASK (VM_FF_CHECK_VM_STATE | VM_FF_DBGF | VM_FF_REQUEST | VM_FF_EMT_RENDEZVOUS)
+/** Externally VMCPU forced actions. Used to quit the idle/wait loop. */
+#define VMCPU_FF_EXTERNAL_SUSPENDED_MASK (VMCPU_FF_REQUEST)
+
+/** Externally forced VM actions. Used to quit the idle/wait loop. */
+#define VM_FF_EXTERNAL_HALTED_MASK ( VM_FF_CHECK_VM_STATE | VM_FF_DBGF | VM_FF_REQUEST \
+ | VM_FF_PDM_QUEUES | VM_FF_PDM_DMA | VM_FF_EMT_RENDEZVOUS)
+/** Externally forced VMCPU actions. Used to quit the idle/wait loop. */
+#define VMCPU_FF_EXTERNAL_HALTED_MASK (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_REQUEST | VMCPU_FF_TIMER)
+
+/** High priority VM pre-execution actions. */
+#define VM_FF_HIGH_PRIORITY_PRE_MASK ( VM_FF_CHECK_VM_STATE | VM_FF_DBGF | VM_FF_TM_VIRTUAL_SYNC \
+ | VM_FF_DEBUG_SUSPEND | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY | VM_FF_EMT_RENDEZVOUS)
+/** High priority VMCPU pre-execution actions. */
+#define VMCPU_FF_HIGH_PRIORITY_PRE_MASK ( VMCPU_FF_TIMER | VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_PGM_SYNC_CR3 \
+ | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL | VMCPU_FF_SELM_SYNC_TSS | VMCPU_FF_TRPM_SYNC_IDT \
+ | VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT | VMCPU_FF_INHIBIT_INTERRUPTS)
+
+/** High priority VM pre raw-mode execution mask. */
+#define VM_FF_HIGH_PRIORITY_PRE_RAW_MASK (VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY)
+/** High priority VMCPU pre raw-mode execution mask. */
+#define VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK ( VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL | VMCPU_FF_SELM_SYNC_TSS | VMCPU_FF_TRPM_SYNC_IDT \
+ | VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT | VMCPU_FF_INHIBIT_INTERRUPTS)
+
+/** High priority post-execution actions. */
+#define VM_FF_HIGH_PRIORITY_POST_MASK (VM_FF_PGM_NO_MEMORY)
+/** High priority post-execution actions. */
+#define VMCPU_FF_HIGH_PRIORITY_POST_MASK (VMCPU_FF_PDM_CRITSECT|VMCPU_FF_CSAM_PENDING_ACTION)
+
+/** Normal priority VM post-execution actions. */
+#define VM_FF_NORMAL_PRIORITY_POST_MASK ( VM_FF_CHECK_VM_STATE | VM_FF_DBGF | VM_FF_RESET \
+ | VM_FF_PGM_NO_MEMORY | VM_FF_EMT_RENDEZVOUS)
+/** Normal priority VMCPU post-execution actions. */
+#define VMCPU_FF_NORMAL_PRIORITY_POST_MASK (VMCPU_FF_CSAM_SCAN_PAGE)
+
+/** Normal priority VM actions. */
+#define VM_FF_NORMAL_PRIORITY_MASK (VM_FF_REQUEST | VM_FF_PDM_QUEUES | VM_FF_PDM_DMA | VM_FF_REM_HANDLER_NOTIFY | VM_FF_EMT_RENDEZVOUS)
+/** Normal priority VMCPU actions. */
+#define VMCPU_FF_NORMAL_PRIORITY_MASK (VMCPU_FF_REQUEST)
+
+/** Flags to clear before resuming guest execution. */
+#define VMCPU_FF_RESUME_GUEST_MASK (VMCPU_FF_TO_R3)
+
+/** VM Flags that cause the HWACCM loops to go back to ring-3. */
+#define VM_FF_HWACCM_TO_R3_MASK (VM_FF_TM_VIRTUAL_SYNC | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY | VM_FF_PDM_QUEUES | VM_FF_EMT_RENDEZVOUS)
+/** VMCPU Flags that cause the HWACCM loops to go back to ring-3. */
+#define VMCPU_FF_HWACCM_TO_R3_MASK (VMCPU_FF_TO_R3 | VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT)
+
+/** All the forced VM flags. */
+#define VM_FF_ALL_MASK (~0U)
+/** All the forced VMCPU flags. */
+#define VMCPU_FF_ALL_MASK (~0U)
+
+/** All the forced VM flags except those related to raw-mode and hardware
+ * assisted execution. */
+#define VM_FF_ALL_REM_MASK (~(VM_FF_HIGH_PRIORITY_PRE_RAW_MASK) | VM_FF_PGM_NO_MEMORY)
+/** All the forced VMCPU flags except those related to raw-mode and hardware
+ * assisted execution. */
+#define VMCPU_FF_ALL_REM_MASK (~(VMCPU_FF_HIGH_PRIORITY_PRE_RAW_MASK | VMCPU_FF_CSAM_PENDING_ACTION | VMCPU_FF_PDM_CRITSECT | VMCPU_FF_TLB_FLUSH | VMCPU_FF_TLB_SHOOTDOWN))
+
+/** @} */
+
+/** @def VM_FF_SET
+ * Sets a force action flag.
+ *
+ * @param pVM VM Handle.
+ * @param fFlag The flag to set.
+ */
+#if 1
+# define VM_FF_SET(pVM, fFlag) ASMAtomicOrU32(&(pVM)->fGlobalForcedActions, (fFlag))
+#else
+# define VM_FF_SET(pVM, fFlag) \
+ do { ASMAtomicOrU32(&(pVM)->fGlobalForcedActions, (fFlag)); \
+ RTLogPrintf("VM_FF_SET : %08x %s - %s(%d) %s\n", (pVM)->fGlobalForcedActions, #fFlag, __FILE__, __LINE__, __FUNCTION__); \
+ } while (0)
+#endif
+
+/** @def VMCPU_FF_SET
+ * Sets a force action flag for the given VCPU.
+ *
+ * @param pVCpu VMCPU Handle.
+ * @param fFlag The flag to set.
+ */
+#define VMCPU_FF_SET(pVCpu, fFlag) ASMAtomicOrU32(&(pVCpu)->fLocalForcedActions, (fFlag))
+
+/** @def VM_FF_CLEAR
+ * Clears a force action flag.
+ *
+ * @param pVM VM Handle.
+ * @param fFlag The flag to clear.
+ */
+#if 1
+# define VM_FF_CLEAR(pVM, fFlag) ASMAtomicAndU32(&(pVM)->fGlobalForcedActions, ~(fFlag))
+#else
+# define VM_FF_CLEAR(pVM, fFlag) \
+ do { ASMAtomicAndU32(&(pVM)->fGlobalForcedActions, ~(fFlag)); \
+ RTLogPrintf("VM_FF_CLEAR: %08x %s - %s(%d) %s\n", (pVM)->fGlobalForcedActions, #fFlag, __FILE__, __LINE__, __FUNCTION__); \
+ } while (0)
+#endif
+
+/** @def VMCPU_FF_CLEAR
+ * Clears a force action flag for the given VCPU.
+ *
+ * @param pVCpu VMCPU Handle.
+ * @param fFlag The flag to clear.
+ */
+#define VMCPU_FF_CLEAR(pVCpu, fFlag) ASMAtomicAndU32(&(pVCpu)->fLocalForcedActions, ~(fFlag))
+
+/** @def VM_FF_ISSET
+ * Checks if a force action flag is set.
+ *
+ * @param pVM VM Handle.
+ * @param fFlag The flag to check.
+ */
+#define VM_FF_IS_SET(pVM, fFlag) (((pVM)->fGlobalForcedActions & (fFlag)) == (fFlag))
+/** @deprecated */
+#define VM_FF_ISSET(pVM, fFlag) VM_FF_IS_SET(pVM, fFlag)
+
+/** @def VMCPU_FF_ISSET
+ * Checks if a force action flag is set for the given VCPU.
+ *
+ * @param pVCpu VMCPU Handle.
+ * @param fFlag The flag to check.
+ */
+#define VMCPU_FF_IS_SET(pVCpu, fFlag) (((pVCpu)->fLocalForcedActions & (fFlag)) == (fFlag))
+/** @deprecated */
+#define VMCPU_FF_ISSET(pVCpu, fFlag) VMCPU_FF_IS_SET(pVCpu, fFlag)
+
+/** @def VM_FF_ISPENDING
+ * Checks if one or more force action in the specified set is pending.
+ *
+ * @param pVM VM Handle.
+ * @param fFlags The flags to check for.
+ */
+#define VM_FF_IS_PENDING(pVM, fFlags) ((pVM)->fGlobalForcedActions & (fFlags))
+/** @deprecated */
+#define VM_FF_ISPENDING(pVM, fFlags) VM_FF_IS_PENDING(pVM, fFlags)
+
+/** @def VM_FF_TESTANDCLEAR
+ * Checks if one (!) force action in the specified set is pending and clears it atomically
+ *
+ * @returns true if the bit was set.
+ * @returns false if the bit was clear.
+ * @param pVM VM Handle.
+ * @param iBit Bit position to check and clear
+ */
+#define VM_FF_TEST_AND_CLEAR(pVM, iBit) (ASMAtomicBitTestAndClear(&(pVM)->fGlobalForcedActions, iBit##_BIT))
+/** @deprecated */
+#define VM_FF_TESTANDCLEAR(pVM, iBit) (ASMAtomicBitTestAndClear(&(pVM)->fGlobalForcedActions, iBit##_BIT))
+
+/** @def VMCPU_FF_TESTANDCLEAR
+ * Checks if one (!) force action in the specified set is pending and clears it atomically
+ *
+ * @returns true if the bit was set.
+ * @returns false if the bit was clear.
+ * @param pVCpu VMCPU Handle.
+ * @param iBit Bit position to check and clear
+ */
+#define VMCPU_FF_TEST_AND_CLEAR(pVCpu, iBit) (ASMAtomicBitTestAndClear(&(pVCpu)->fLocalForcedActions, iBit##_BIT))
+/** @deprecated */
+#define VMCPU_FF_TESTANDCLEAR(pVCpu, iBit) (ASMAtomicBitTestAndClear(&(pVCpu)->fLocalForcedActions, iBit##_BIT))
+
+/** @def VMCPU_FF_ISPENDING
+ * Checks if one or more force action in the specified set is pending for the given VCPU.
+ *
+ * @param pVCpu VMCPU Handle.
+ * @param fFlags The flags to check for.
+ */
+#define VMCPU_FF_IS_PENDING(pVCpu, fFlags) ((pVCpu)->fLocalForcedActions & (fFlags))
+/** @deprecated */
+#define VMCPU_FF_ISPENDING(pVCpu, fFlags) VMCPU_FF_IS_PENDING(pVCpu, fFlags)
+
+/** @def VM_FF_ISPENDING
+ * Checks if one or more force action in the specified set is pending while one
+ * or more other ones are not.
+ *
+ * @param pVM VM Handle.
+ * @param fFlags The flags to check for.
+ * @param fExcpt The flags that should not be set.
+ */
+#define VM_FF_IS_PENDING_EXCEPT(pVM, fFlags, fExcpt) ( ((pVM)->fGlobalForcedActions & (fFlags)) && !((pVM)->fGlobalForcedActions & (fExcpt)) )
+
+/** @def VMCPU_FF_IS_PENDING_EXCEPT
+ * Checks if one or more force action in the specified set is pending for the given
+ * VCPU while one or more other ones are not.
+ *
+ * @param pVCpu VMCPU Handle.
+ * @param fFlags The flags to check for.
+ * @param fExcpt The flags that should not be set.
+ */
+#define VMCPU_FF_IS_PENDING_EXCEPT(pVCpu, fFlags, fExcpt) ( ((pVCpu)->fLocalForcedActions & (fFlags)) && !((pVCpu)->fLocalForcedActions & (fExcpt)) )
+
+/** @def VM_IS_EMT
+ * Checks if the current thread is the emulation thread (EMT).
+ *
+ * @remark The ring-0 variation will need attention if we expand the ring-0
+ * code to let threads other than EMT mess around with the VM.
+ */
+#ifdef IN_RC
+# define VM_IS_EMT(pVM) true
+#else
+# define VM_IS_EMT(pVM) (VMMGetCpu(pVM) != NULL)
+#endif
+
+/** @def VMCPU_IS_EMT
+ * Checks if the current thread is the emulation thread (EMT) for the specified
+ * virtual CPU.
+ */
+#ifdef IN_RC
+# define VMCPU_IS_EMT(pVCpu) true
+#else
+# define VMCPU_IS_EMT(pVCpu) ((pVCpu) && ((pVCpu) == VMMGetCpu((pVCpu)->CTX_SUFF(pVM))))
+#endif
+
+/** @def VM_ASSERT_EMT
+ * Asserts that the current thread IS the emulation thread (EMT).
+ */
+#ifdef IN_RC
+# define VM_ASSERT_EMT(pVM) Assert(VM_IS_EMT(pVM))
+#elif defined(IN_RING0)
+# define VM_ASSERT_EMT(pVM) Assert(VM_IS_EMT(pVM))
+#else
+# define VM_ASSERT_EMT(pVM) \
+ AssertMsg(VM_IS_EMT(pVM), \
+ ("Not emulation thread! Thread=%RTnthrd ThreadEMT=%RTnthrd\n", RTThreadNativeSelf(), VMR3GetVMCPUNativeThread(pVM)))
+#endif
+
+/** @def VMCPU_ASSERT_EMT
+ * Asserts that the current thread IS the emulation thread (EMT) of the
+ * specified virtual CPU.
+ */
+#ifdef IN_RC
+# define VMCPU_ASSERT_EMT(pVCpu) Assert(VMCPU_IS_EMT(pVCpu))
+#elif defined(IN_RING0)
+# define VMCPU_ASSERT_EMT(pVCpu) Assert(VMCPU_IS_EMT(pVCpu))
+#else
+# define VMCPU_ASSERT_EMT(pVCpu) \
+ AssertMsg(VMCPU_IS_EMT(pVCpu), \
+ ("Not emulation thread! Thread=%RTnthrd ThreadEMT=%RTnthrd idCpu=%#x\n", \
+ RTThreadNativeSelf(), (pVCpu)->hNativeThread, (pVCpu)->idCpu))
+#endif
+
+/** @def VM_ASSERT_EMT_RETURN
+ * Asserts that the current thread IS the emulation thread (EMT) and returns if it isn't.
+ */
+#ifdef IN_RC
+# define VM_ASSERT_EMT_RETURN(pVM, rc) AssertReturn(VM_IS_EMT(pVM), (rc))
+#elif defined(IN_RING0)
+# define VM_ASSERT_EMT_RETURN(pVM, rc) AssertReturn(VM_IS_EMT(pVM), (rc))
+#else
+# define VM_ASSERT_EMT_RETURN(pVM, rc) \
+ AssertMsgReturn(VM_IS_EMT(pVM), \
+ ("Not emulation thread! Thread=%RTnthrd ThreadEMT=%RTnthrd\n", RTThreadNativeSelf(), VMR3GetVMCPUNativeThread(pVM)), \
+ (rc))
+#endif
+
+/** @def VMCPU_ASSERT_EMT_RETURN
+ * Asserts that the current thread IS the emulation thread (EMT) and returns if it isn't.
+ */
+#ifdef IN_RC
+# define VMCPU_ASSERT_EMT_RETURN(pVCpu, rc) AssertReturn(VMCPU_IS_EMT(pVCpu), (rc))
+#elif defined(IN_RING0)
+# define VMCPU_ASSERT_EMT_RETURN(pVCpu, rc) AssertReturn(VMCPU_IS_EMT(pVCpu), (rc))
+#else
+# define VMCPU_ASSERT_EMT_RETURN(pVCpu, rc) \
+ AssertMsg(VMCPU_IS_EMT(pVCpu), \
+ ("Not emulation thread! Thread=%RTnthrd ThreadEMT=%RTnthrd idCpu=%#x\n", \
+ RTThreadNativeSelf(), (pVCpu)->hNativeThread, (pVCpu)->idCpu), \
+ (rc))
+#endif
+
+/** @def VMCPU_ASSERT_EMT_OR_GURU
+ * Asserts that the current thread IS the emulation thread (EMT) of the
+ * specified virtual CPU.
+ */
+#if defined(IN_RC) || defined(IN_RING0)
+# define VMCPU_ASSERT_EMT_OR_GURU(pVCpu) Assert( VMCPU_IS_EMT(pVCpu) \
+ || pVCpu->CTX_SUFF(pVM)->enmVMState == VMSTATE_GURU_MEDITATION \
+ || pVCpu->CTX_SUFF(pVM)->enmVMState == VMSTATE_GURU_MEDITATION_LS )
+#else
+# define VMCPU_ASSERT_EMT_OR_GURU(pVCpu) \
+ AssertMsg( VMCPU_IS_EMT(pVCpu) \
+ || pVCpu->CTX_SUFF(pVM)->enmVMState == VMSTATE_GURU_MEDITATION \
+ || pVCpu->CTX_SUFF(pVM)->enmVMState == VMSTATE_GURU_MEDITATION_LS, \
+ ("Not emulation thread! Thread=%RTnthrd ThreadEMT=%RTnthrd idCpu=%#x\n", \
+ RTThreadNativeSelf(), (pVCpu)->hNativeThread, (pVCpu)->idCpu))
+#endif
+
+/** @def VMCPU_ASSERT_EMT_OR_NOT_RUNNING
+ * Asserts that the current thread IS the emulation thread (EMT) of the
+ * specified virtual CPU when the VM is running.
+ */
+#if defined(IN_RC) || defined(IN_RING0)
+# define VMCPU_ASSERT_EMT_OR_NOT_RUNNING(pVCpu) \
+ Assert( VMCPU_IS_EMT(pVCpu) \
+ || pVCpu->CTX_SUFF(pVM)->enmVMState == VMSTATE_RUNNING \
+ || pVCpu->CTX_SUFF(pVM)->enmVMState == VMSTATE_RUNNING_LS \
+ || pVCpu->CTX_SUFF(pVM)->enmVMState == VMSTATE_RUNNING_FT )
+#else
+# define VMCPU_ASSERT_EMT_OR_NOT_RUNNING(pVCpu) \
+ AssertMsg( VMCPU_IS_EMT(pVCpu) \
+ || pVCpu->CTX_SUFF(pVM)->enmVMState == VMSTATE_RUNNING \
+ || pVCpu->CTX_SUFF(pVM)->enmVMState == VMSTATE_RUNNING_LS \
+ || pVCpu->CTX_SUFF(pVM)->enmVMState == VMSTATE_RUNNING_FT, \
+ ("Not emulation thread! Thread=%RTnthrd ThreadEMT=%RTnthrd idCpu=%#x\n", \
+ RTThreadNativeSelf(), (pVCpu)->hNativeThread, (pVCpu)->idCpu))
+#endif
+
+/** @def VM_ASSERT_EMT0
+ * Asserts that the current thread IS emulation thread \#0 (EMT0).
+ */
+#define VM_ASSERT_EMT0(pVM) VMCPU_ASSERT_EMT(&(pVM)->aCpus[0])
+
+/** @def VM_ASSERT_EMT0_RETURN
+ * Asserts that the current thread IS emulation thread \#0 (EMT0) and returns if
+ * it isn't.
+ */
+#define VM_ASSERT_EMT0_RETURN(pVM, rc) VMCPU_ASSERT_EMT_RETURN(&(pVM)->aCpus[0], (rc))
+
+
+/**
+ * Asserts that the current thread is NOT the emulation thread.
+ */
+#define VM_ASSERT_OTHER_THREAD(pVM) \
+ AssertMsg(!VM_IS_EMT(pVM), ("Not other thread!!\n"))
+
+
+/** @def VM_ASSERT_STATE_RETURN
+ * Asserts a certain VM state.
+ */
+#define VM_ASSERT_STATE(pVM, _enmState) \
+ AssertMsg((pVM)->enmVMState == (_enmState), \
+ ("state %s, expected %s\n", VMGetStateName((pVM)->enmVMState), VMGetStateName(_enmState)))
+
+/** @def VM_ASSERT_STATE_RETURN
+ * Asserts a certain VM state and returns if it doesn't match.
+ */
+#define VM_ASSERT_STATE_RETURN(pVM, _enmState, rc) \
+ AssertMsgReturn((pVM)->enmVMState == (_enmState), \
+ ("state %s, expected %s\n", VMGetStateName((pVM)->enmVMState), VMGetStateName(_enmState)), \
+ (rc))
+
+/** @def VM_ASSERT_VALID_EXT_RETURN
+ * Asserts a the VM handle is valid for external access, i.e. not being
+ * destroy or terminated.
+ */
+#define VM_ASSERT_VALID_EXT_RETURN(pVM, rc) \
+ AssertMsgReturn( RT_VALID_ALIGNED_PTR(pVM, PAGE_SIZE) \
+ && ( (unsigned)(pVM)->enmVMState < (unsigned)VMSTATE_DESTROYING \
+ || ( (unsigned)(pVM)->enmVMState == (unsigned)VMSTATE_DESTROYING \
+ && VM_IS_EMT(pVM))), \
+ ("pVM=%p state %s\n", (pVM), RT_VALID_ALIGNED_PTR(pVM, PAGE_SIZE) \
+ ? VMGetStateName(pVM->enmVMState) : ""), \
+ (rc))
+
+/** @def VMCPU_ASSERT_VALID_EXT_RETURN
+ * Asserts a the VMCPU handle is valid for external access, i.e. not being
+ * destroy or terminated.
+ */
+#define VMCPU_ASSERT_VALID_EXT_RETURN(pVCpu, rc) \
+ AssertMsgReturn( RT_VALID_ALIGNED_PTR(pVCpu, 64) \
+ && RT_VALID_ALIGNED_PTR((pVCpu)->CTX_SUFF(pVM), PAGE_SIZE) \
+ && (unsigned)(pVCpu)->CTX_SUFF(pVM)->enmVMState < (unsigned)VMSTATE_DESTROYING, \
+ ("pVCpu=%p pVM=%p state %s\n", (pVCpu), RT_VALID_ALIGNED_PTR(pVCpu, 64) ? (pVCpu)->CTX_SUFF(pVM) : NULL, \
+ RT_VALID_ALIGNED_PTR(pVCpu, 64) && RT_VALID_ALIGNED_PTR((pVCpu)->CTX_SUFF(pVM), PAGE_SIZE) \
+ ? VMGetStateName((pVCpu)->pVMR3->enmVMState) : ""), \
+ (rc))
+
+#endif /* !VBOX_FOR_DTRACE_LIB */
+
+
+
+/** This is the VM structure.
+ *
+ * It contains (nearly?) all the VM data which have to be available in all
+ * contexts. Even if it contains all the data the idea is to use APIs not
+ * to modify all the members all around the place. Therefore we make use of
+ * unions to hide everything which isn't local to the current source module.
+ * This means we'll have to pay a little bit of attention when adding new
+ * members to structures in the unions and make sure to keep the padding sizes
+ * up to date.
+ *
+ * Run tstVMStructSize after update!
+ */
+typedef struct VM
+{
+ /** The state of the VM.
+ * This field is read only to everyone except the VM and EM. */
+ VMSTATE volatile enmVMState;
+ /** Forced action flags.
+ * See the VM_FF_* \#defines. Updated atomically.
+ */
+ volatile uint32_t fGlobalForcedActions;
+ /** Pointer to the array of page descriptors for the VM structure allocation. */
+ R3PTRTYPE(PSUPPAGE) paVMPagesR3;
+ /** Session handle. For use when calling SUPR0 APIs. */
+ PSUPDRVSESSION pSession;
+ /** Pointer to the ring-3 VM structure. */
+ PUVM pUVM;
+ /** Ring-3 Host Context VM Pointer. */
+ R3PTRTYPE(struct VM *) pVMR3;
+ /** Ring-0 Host Context VM Pointer. */
+ R0PTRTYPE(struct VM *) pVMR0;
+ /** Raw-mode Context VM Pointer. */
+ RCPTRTYPE(struct VM *) pVMRC;
+
+ /** The GVM VM handle. Only the GVM should modify this field. */
+ uint32_t hSelf;
+ /** Number of virtual CPUs. */
+ uint32_t cCpus;
+ /** CPU excution cap (1-100) */
+ uint32_t uCpuExecutionCap;
+
+ /** Size of the VM structure including the VMCPU array. */
+ uint32_t cbSelf;
+
+ /** Offset to the VMCPU array starting from beginning of this structure. */
+ uint32_t offVMCPU;
+
+ /**
+ * VMMSwitcher assembly entry point returning to host context.
+ *
+ * Depending on how the host handles the rc status given in @a eax, this may
+ * return and let the caller resume whatever it was doing prior to the call.
+ *
+ *
+ * @param eax The return code, register.
+ * @remark Assume interrupts disabled.
+ * @remark This method pointer lives here because TRPM needs it.
+ */
+ RTRCPTR pfnVMMRCToHostAsm/*(int32_t eax)*/;
+
+ /**
+ * VMMSwitcher assembly entry point returning to host context without saving the
+ * raw-mode context (hyper) registers.
+ *
+ * Unlike pfnVMMRC2HCAsm, this will not return to the caller. Instead it
+ * expects the caller to save a RC context in CPUM where one might return if the
+ * return code indicate that this is possible.
+ *
+ * This method pointer lives here because TRPM needs it.
+ *
+ * @param eax The return code, register.
+ * @remark Assume interrupts disabled.
+ * @remark This method pointer lives here because TRPM needs it.
+ */
+ RTRCPTR pfnVMMRCToHostAsmNoReturn/*(int32_t eax)*/;
+
+ /** @name Various items that are frequently accessed.
+ * @{ */
+ /** Whether to recompile user mode code or run it raw/hm. */
+ bool fRecompileUser;
+ /** Whether to recompile supervisor mode code or run it raw/hm. */
+ bool fRecompileSupervisor;
+ /** PATM enabled flag.
+ * This is placed here for performance reasons. */
+ bool fPATMEnabled;
+ /** CSAM enabled flag.
+ * This is placed here for performance reasons. */
+ bool fCSAMEnabled;
+ /** Hardware VM support is available and enabled.
+ * This is placed here for performance reasons. */
+ bool fHWACCMEnabled;
+ /** Hardware VM support is required and non-optional.
+ * This is initialized together with the rest of the VM structure. */
+ bool fHwVirtExtForced;
+ /** Set when this VM is the master FT node. */
+ bool fFaultTolerantMaster;
+ /** Large page enabled flag. */
+ bool fUseLargePages;
+ /** @} */
+
+ /** Alignment padding.. */
+ uint32_t uPadding1;
+
+ /** @name Debugging
+ * @{ */
+ /** Raw-mode Context VM Pointer. */
+ RCPTRTYPE(RTTRACEBUF) hTraceBufRC;
+ /** Ring-3 Host Context VM Pointer. */
+ R3PTRTYPE(RTTRACEBUF) hTraceBufR3;
+ /** Ring-0 Host Context VM Pointer. */
+ R0PTRTYPE(RTTRACEBUF) hTraceBufR0;
+ /** @} */
+
+#if HC_ARCH_BITS == 32
+ /** Alignment padding.. */
+ uint32_t uPadding2;
+#endif
+
+ /** @name Switcher statistics (remove)
+ * @{ */
+ /** Profiling the total time from Qemu to GC. */
+ STAMPROFILEADV StatTotalQemuToGC;
+ /** Profiling the total time from GC to Qemu. */
+ STAMPROFILEADV StatTotalGCToQemu;
+ /** Profiling the total time spent in GC. */
+ STAMPROFILEADV StatTotalInGC;
+ /** Profiling the total time spent not in Qemu. */
+ STAMPROFILEADV StatTotalInQemu;
+ /** Profiling the VMMSwitcher code for going to GC. */
+ STAMPROFILEADV StatSwitcherToGC;
+ /** Profiling the VMMSwitcher code for going to HC. */
+ STAMPROFILEADV StatSwitcherToHC;
+ STAMPROFILEADV StatSwitcherSaveRegs;
+ STAMPROFILEADV StatSwitcherSysEnter;
+ STAMPROFILEADV StatSwitcherDebug;
+ STAMPROFILEADV StatSwitcherCR0;
+ STAMPROFILEADV StatSwitcherCR4;
+ STAMPROFILEADV StatSwitcherJmpCR3;
+ STAMPROFILEADV StatSwitcherRstrRegs;
+ STAMPROFILEADV StatSwitcherLgdt;
+ STAMPROFILEADV StatSwitcherLidt;
+ STAMPROFILEADV StatSwitcherLldt;
+ STAMPROFILEADV StatSwitcherTSS;
+ /** @} */
+
+ /** Padding - the unions must be aligned on a 64 bytes boundary and the unions
+ * must start at the same offset on both 64-bit and 32-bit hosts. */
+ uint8_t abAlignment3[(HC_ARCH_BITS == 32 ? 24 : 0) + 40];
+
+ /** CPUM part. */
+ union
+ {
+#ifdef ___CPUMInternal_h
+ struct CPUM s;
+#endif
+ uint8_t padding[1536]; /* multiple of 64 */
+ } cpum;
+
+ /** VMM part. */
+ union
+ {
+#ifdef ___VMMInternal_h
+ struct VMM s;
+#endif
+ uint8_t padding[1600]; /* multiple of 64 */
+ } vmm;
+
+ /** PGM part. */
+ union
+ {
+#ifdef ___PGMInternal_h
+ struct PGM s;
+#endif
+ uint8_t padding[4096*2+6080]; /* multiple of 64 */
+ } pgm;
+
+ /** HWACCM part. */
+ union
+ {
+#ifdef ___HWACCMInternal_h
+ struct HWACCM s;
+#endif
+ uint8_t padding[5376]; /* multiple of 64 */
+ } hwaccm;
+
+ /** TRPM part. */
+ union
+ {
+#ifdef ___TRPMInternal_h
+ struct TRPM s;
+#endif
+ uint8_t padding[5248]; /* multiple of 64 */
+ } trpm;
+
+ /** SELM part. */
+ union
+ {
+#ifdef ___SELMInternal_h
+ struct SELM s;
+#endif
+ uint8_t padding[768]; /* multiple of 64 */
+ } selm;
+
+ /** MM part. */
+ union
+ {
+#ifdef ___MMInternal_h
+ struct MM s;
+#endif
+ uint8_t padding[192]; /* multiple of 64 */
+ } mm;
+
+ /** PDM part. */
+ union
+ {
+#ifdef ___PDMInternal_h
+ struct PDM s;
+#endif
+ uint8_t padding[1920]; /* multiple of 64 */
+ } pdm;
+
+ /** IOM part. */
+ union
+ {
+#ifdef ___IOMInternal_h
+ struct IOM s;
+#endif
+ uint8_t padding[832]; /* multiple of 64 */
+ } iom;
+
+ /** PATM part. */
+ union
+ {
+#ifdef ___PATMInternal_h
+ struct PATM s;
+#endif
+ uint8_t padding[768]; /* multiple of 64 */
+ } patm;
+
+ /** CSAM part. */
+ union
+ {
+#ifdef ___CSAMInternal_h
+ struct CSAM s;
+#endif
+ uint8_t padding[1088]; /* multiple of 64 */
+ } csam;
+
+ /** EM part. */
+ union
+ {
+#ifdef ___EMInternal_h
+ struct EM s;
+#endif
+ uint8_t padding[256]; /* multiple of 64 */
+ } em;
+
+ /** TM part. */
+ union
+ {
+#ifdef ___TMInternal_h
+ struct TM s;
+#endif
+ uint8_t padding[2432]; /* multiple of 64 */
+ } tm;
+
+ /** DBGF part. */
+ union
+ {
+#ifdef ___DBGFInternal_h
+ struct DBGF s;
+#endif
+ uint8_t padding[2368]; /* multiple of 64 */
+ } dbgf;
+
+ /** SSM part. */
+ union
+ {
+#ifdef ___SSMInternal_h
+ struct SSM s;
+#endif
+ uint8_t padding[128]; /* multiple of 64 */
+ } ssm;
+
+ /** FTM part. */
+ union
+ {
+#ifdef ___FTMInternal_h
+ struct FTM s;
+#endif
+ uint8_t padding[512]; /* multiple of 64 */
+ } ftm;
+
+ /** REM part. */
+ union
+ {
+#ifdef ___REMInternal_h
+ struct REM s;
+#endif
+ uint8_t padding[0x11100]; /* multiple of 64 */
+ } rem;
+
+ /* ---- begin small stuff ---- */
+
+ /** VM part. */
+ union
+ {
+#ifdef ___VMInternal_h
+ struct VMINT s;
+#endif
+ uint8_t padding[24]; /* multiple of 8 */
+ } vm;
+
+ /** CFGM part. */
+ union
+ {
+#ifdef ___CFGMInternal_h
+ struct CFGM s;
+#endif
+ uint8_t padding[8]; /* multiple of 8 */
+ } cfgm;
+
+
+ /** Padding for aligning the cpu array on a page boundary. */
+ uint8_t abAlignment2[542];
+
+ /* ---- end small stuff ---- */
+
+ /** VMCPU array for the configured number of virtual CPUs.
+ * Must be aligned on a page boundary for TLB hit reasons as well as
+ * alignment of VMCPU members. */
+ VMCPU aCpus[1];
+} VM;
+
+
+#ifdef IN_RC
+RT_C_DECLS_BEGIN
+
+/** The VM structure.
+ * This is imported from the VMMGCBuiltin module, i.e. it's a one
+ * of those magic globals which we should avoid using.
+ */
+extern DECLIMPORT(VM) g_VM;
+
+RT_C_DECLS_END
+#endif
+
+/** @} */
+
+#endif
+
diff --git a/include/VBox/vmm/vm.mac b/include/VBox/vmm/vm.mac
new file mode 100644
index 00000000..6d65b0c9
--- /dev/null
+++ b/include/VBox/vmm/vm.mac
@@ -0,0 +1,150 @@
+;; @file
+; VM - The Virtual Machine.
+;
+
+;
+; Copyright (C) 2006-2012 Oracle Corporation
+;
+; This file is part of VirtualBox Open Source Edition (OSE), as
+; available from http://www.virtualbox.org. This file is free software;
+; you can redistribute it and/or modify it under the terms of the GNU
+; 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.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+; VirtualBox OSE distribution, in which case the provisions of the
+; CDDL are applicable instead of those of the GPL.
+;
+; You may elect to license modified versions of this file under the
+; terms and conditions of either the GPL or the CDDL or both.
+;
+
+%ifndef ___VBox_vmm_vm_mac
+%define ___VBox_vmm_vm_mac
+
+%include "VBox/vmm/stam.mac"
+
+;/** This action forces the VM to service check and pending interrups on the APIC. */
+%define VMCPU_FF_INTERRUPT_APIC (1 << 0)
+;/** This action forces the VM to service check and pending interrups on the PIC. */
+%define VMCPU_FF_INTERRUPT_PIC (1 << 1)
+;/** This action forces the VM to schedule and run pending timer (TM). */
+%define VMCPU_FF_TIMER (1 << 2)
+;/** This action forces the VM to service pending requests from other
+; * thread or requests which must be executed in another context. */
+%define VMCPU_FF_REQUEST (1 << 9)
+
+;;
+; This is part of the VM structure.
+struc VM
+ .enmVMState resd 1
+ .fGlobalForcedActions resd 1
+ .paVMPagesR3 RTR3PTR_RES 1
+ .pSession RTR0PTR_RES 1
+ .pUVM RTR3PTR_RES 1
+ .pVMR3 RTR3PTR_RES 1
+ .pVMR0 RTR0PTR_RES 1
+ .pVMRC RTRCPTR_RES 1
+ .hSelf resd 1
+ .cCpus resd 1
+ .uCpuExecutionCap resd 1
+ .cbSelf resd 1
+ .offVMCPU resd 1
+ .pfnVMMRCToHostAsm resd 1
+ .pfnVMMRCToHostAsmNoReturn resd 1
+ .fRecompileUser resb 1
+ .fRecompileSupervisor resb 1
+ .fPATMEnabled resb 1
+ .fCSAMEnabled resb 1
+ .fHWACCMEnabled resb 1
+ .fHwVirtExtForced resb 1
+ .fFaultTolerantMaster resb 1
+ .fUseLargePages resb 1
+
+ .uPadding1 resd 1
+
+ .hTraceBufRC RTRCPTR_RES 1
+ .hTraceBufR3 RTR3PTR_RES 1
+ .hTraceBufR0 RTR0PTR_RES 1
+
+ alignb 8
+
+ .StatTotalQemuToGC resb STAMPROFILEADV_size
+ .StatTotalGCToQemu resb STAMPROFILEADV_size
+ .StatTotalInGC resb STAMPROFILEADV_size
+ .StatTotalInQemu resb STAMPROFILEADV_size
+ .StatSwitcherToGC resb STAMPROFILEADV_size
+ .StatSwitcherToHC resb STAMPROFILEADV_size
+ .StatSwitcherSaveRegs resb STAMPROFILEADV_size
+ .StatSwitcherSysEnter resb STAMPROFILEADV_size
+ .StatSwitcherDebug resb STAMPROFILEADV_size
+ .StatSwitcherCR0 resb STAMPROFILEADV_size
+ .StatSwitcherCR4 resb STAMPROFILEADV_size
+ .StatSwitcherJmpCR3 resb STAMPROFILEADV_size
+ .StatSwitcherRstrRegs resb STAMPROFILEADV_size
+ .StatSwitcherLgdt resb STAMPROFILEADV_size
+ .StatSwitcherLidt resb STAMPROFILEADV_size
+ .StatSwitcherLldt resb STAMPROFILEADV_size
+ .StatSwitcherTSS resb STAMPROFILEADV_size
+
+%ifndef HC_ARCH_BITS
+ %error "Missing HC_ARCH_BITS"
+%endif
+%if HC_ARCH_BITS == 32
+ .abAlignment3 resb 16
+%else
+; .abAlignment3 resb 16
+%endif
+
+ alignb 64
+ .cpum resb 1536
+ .vmm resb 1536
+
+endstruc
+
+;;
+; This is part of the VMCPU structure.
+struc VMCPU
+ .fLocalForcedActions resd 1
+ .enmState resd 1
+ .pUVCpu RTR3PTR_RES 1
+ .pVMR3 RTR3PTR_RES 1
+ .pVMR0 RTR0PTR_RES 1
+ .pVMRC RTRCPTR_RES 1
+ .idCpu resd 1
+
+ .hNativeThread RTR0PTR_RES 1
+ .hNativeThreadR0 RTR0PTR_RES 1
+ .idHostCpu resd 1
+ .fTraceGroups resd 1
+%if HC_ARCH_BITS == 32
+ .abAlignment1 resb 16+64
+%else
+ .abAlignment1 resb 60
+%endif
+ .uAdHoc resd 1
+ .aStatAdHoc resb STAMPROFILEADV_size * 8
+
+ alignb 64
+
+ .cpum resb 3584
+ .hwaccm resb 5376
+ .em resb 1472
+ .iem resb 3072
+ .trpm resb 128
+ .tm resb 384
+ .vmm resb 640
+ .pdm resb 128
+ .iom resb 512
+ .dbgf resb 64
+ alignb 4096
+ .pgm resb 4096
+endstruc
+
+
+%endif
+
diff --git a/include/VBox/vmm/vmapi.h b/include/VBox/vmm/vmapi.h
new file mode 100644
index 00000000..b15fc7f6
--- /dev/null
+++ b/include/VBox/vmm/vmapi.h
@@ -0,0 +1,441 @@
+/** @file
+ * VM - The Virtual Machine, API.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_vmapi_h
+#define ___VBox_vmm_vmapi_h
+
+#include <VBox/types.h>
+#include <VBox/vmm/stam.h>
+#include <VBox/vmm/cfgm.h>
+
+#include <iprt/stdarg.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_vmm_apis VM All Contexts API
+ * @ingroup grp_vm
+ * @{ */
+
+/** @def VM_RC_ADDR
+ * Converts a current context address of data within the VM structure to the equivalent
+ * raw-mode address.
+ *
+ * @returns raw-mode virtual address.
+ * @param pVM Pointer to the VM.
+ * @param pvInVM CC Pointer within the VM.
+ */
+#ifdef IN_RING3
+# define VM_RC_ADDR(pVM, pvInVM) ( (RTRCPTR)((RTRCUINTPTR)pVM->pVMRC + (uint32_t)((uintptr_t)(pvInVM) - (uintptr_t)pVM->pVMR3)) )
+#elif defined(IN_RING0)
+# define VM_RC_ADDR(pVM, pvInVM) ( (RTRCPTR)((RTRCUINTPTR)pVM->pVMRC + (uint32_t)((uintptr_t)(pvInVM) - (uintptr_t)pVM->pVMR0)) )
+#else
+# define VM_RC_ADDR(pVM, pvInVM) ( (RTRCPTR)(pvInVM) )
+#endif
+
+/** @def VM_R3_ADDR
+ * Converts a current context address of data within the VM structure to the equivalent
+ * ring-3 host address.
+ *
+ * @returns host virtual address.
+ * @param pVM Pointer to the VM.
+ * @param pvInVM CC pointer within the VM.
+ */
+#ifdef IN_RC
+# define VM_R3_ADDR(pVM, pvInVM) ( (RTR3PTR)((RTR3UINTPTR)pVM->pVMR3 + (uint32_t)((uintptr_t)(pvInVM) - (uintptr_t)pVM->pVMRC)) )
+#elif defined(IN_RING0)
+# define VM_R3_ADDR(pVM, pvInVM) ( (RTR3PTR)((RTR3UINTPTR)pVM->pVMR3 + (uint32_t)((uintptr_t)(pvInVM) - (uintptr_t)pVM->pVMR0)) )
+#else
+# define VM_R3_ADDR(pVM, pvInVM) ( (RTR3PTR)(pvInVM) )
+#endif
+
+
+/** @def VM_R0_ADDR
+ * Converts a current context address of data within the VM structure to the equivalent
+ * ring-0 host address.
+ *
+ * @returns host virtual address.
+ * @param pVM Pointer to the VM.
+ * @param pvInVM CC pointer within the VM.
+ */
+#ifdef IN_RC
+# define VM_R0_ADDR(pVM, pvInVM) ( (RTR0PTR)((RTR0UINTPTR)pVM->pVMR0 + (uint32_t)((uintptr_t)(pvInVM) - (uintptr_t)pVM->pVMRC)) )
+#elif defined(IN_RING3)
+# define VM_R0_ADDR(pVM, pvInVM) ( (RTR0PTR)((RTR0UINTPTR)pVM->pVMR0 + (uint32_t)((uintptr_t)(pvInVM) - (uintptr_t)pVM->pVMR3)) )
+#else
+# define VM_R0_ADDR(pVM, pvInVM) ( (RTR0PTR)(pvInVM) )
+#endif
+
+
+
+/**
+ * VM error callback function.
+ *
+ * @param pVM The VM handle. Can be NULL if an error occurred before
+ * successfully creating a VM.
+ * @param pvUser The user argument.
+ * @param rc VBox status code.
+ * @param RT_SRC_POS_DECL The source position arguments. See RT_SRC_POS and RT_SRC_POS_ARGS.
+ * @param pszFormat Error message format string.
+ * @param args Error message arguments.
+ */
+typedef DECLCALLBACK(void) FNVMATERROR(PVM pVM, void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszError, va_list args);
+/** Pointer to a VM error callback. */
+typedef FNVMATERROR *PFNVMATERROR;
+
+VMMDECL(int) VMSetError(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...);
+VMMDECL(int) VMSetErrorV(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list args);
+
+/** @def VM_SET_ERROR
+ * Macro for setting a simple VM error message.
+ * Don't use '%' in the message!
+ *
+ * @returns rc. Meaning you can do:
+ * @code
+ * return VM_SET_ERROR(pVM, VERR_OF_YOUR_CHOICE, "descriptive message");
+ * @endcode
+ * @param pVM VM handle.
+ * @param rc VBox status code.
+ * @param pszMessage Error message string.
+ * @thread Any
+ */
+#define VM_SET_ERROR(pVM, rc, pszMessage) (VMSetError(pVM, rc, RT_SRC_POS, pszMessage))
+
+
+/**
+ * VM runtime error callback function.
+ *
+ * See VMSetRuntimeError for the detailed description of parameters.
+ *
+ * @param pVM The VM handle.
+ * @param pvUser The user argument.
+ * @param fFlags The error flags.
+ * @param pszErrorId Error ID string.
+ * @param pszFormat Error message format string.
+ * @param va Error message arguments.
+ */
+typedef DECLCALLBACK(void) FNVMATRUNTIMEERROR(PVM pVM, void *pvUser, uint32_t fFlags, const char *pszErrorId,
+ const char *pszFormat, va_list va);
+/** Pointer to a VM runtime error callback. */
+typedef FNVMATRUNTIMEERROR *PFNVMATRUNTIMEERROR;
+
+VMMDECL(int) VMSetRuntimeError(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, ...);
+VMMDECL(int) VMSetRuntimeErrorV(PVM pVM, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list args);
+
+/** @name VMSetRuntimeError fFlags
+ * When no flags are given the VM will continue running and it's up to the front
+ * end to take action on the error condition.
+ *
+ * @{ */
+/** The error is fatal.
+ * The VM is not in a state where it can be saved and will enter a state
+ * where it can no longer execute code. The caller <b>must</b> propagate status
+ * codes. */
+#define VMSETRTERR_FLAGS_FATAL RT_BIT_32(0)
+/** Suspend the VM after, or if possible before, raising the error on EMT. The
+ * caller <b>must</b> propagate status codes. */
+#define VMSETRTERR_FLAGS_SUSPEND RT_BIT_32(1)
+/** Don't wait for the EMT to handle the request.
+ * Only valid when on a worker thread and there is a high risk of a dead
+ * lock. Be careful not to flood the user with errors. */
+#define VMSETRTERR_FLAGS_NO_WAIT RT_BIT_32(2)
+/** @} */
+
+/**
+ * VM state callback function.
+ *
+ * You are not allowed to call any function which changes the VM state from a
+ * state callback, except VMR3Destroy().
+ *
+ * @param pVM The VM handle.
+ * @param enmState The new state.
+ * @param enmOldState The old state.
+ * @param pvUser The user argument.
+ */
+typedef DECLCALLBACK(void) FNVMATSTATE(PVM pVM, VMSTATE enmState, VMSTATE enmOldState, void *pvUser);
+/** Pointer to a VM state callback. */
+typedef FNVMATSTATE *PFNVMATSTATE;
+
+VMMDECL(const char *) VMGetStateName(VMSTATE enmState);
+
+
+/**
+ * Request type.
+ */
+typedef enum VMREQTYPE
+{
+ /** Invalid request. */
+ VMREQTYPE_INVALID = 0,
+ /** VM: Internal. */
+ VMREQTYPE_INTERNAL,
+ /** Maximum request type (exclusive). Used for validation. */
+ VMREQTYPE_MAX
+} VMREQTYPE;
+
+/**
+ * Request state.
+ */
+typedef enum VMREQSTATE
+{
+ /** The state is invalid. */
+ VMREQSTATE_INVALID = 0,
+ /** The request have been allocated and is in the process of being filed. */
+ VMREQSTATE_ALLOCATED,
+ /** The request is queued by the requester. */
+ VMREQSTATE_QUEUED,
+ /** The request is begin processed. */
+ VMREQSTATE_PROCESSING,
+ /** The request is completed, the requester is begin notified. */
+ VMREQSTATE_COMPLETED,
+ /** The request packet is in the free chain. (The requester */
+ VMREQSTATE_FREE
+} VMREQSTATE;
+
+/**
+ * Request flags.
+ */
+typedef enum VMREQFLAGS
+{
+ /** The request returns a VBox status code. */
+ VMREQFLAGS_VBOX_STATUS = 0,
+ /** The request is a void request and have no status code. */
+ VMREQFLAGS_VOID = 1,
+ /** Return type mask. */
+ VMREQFLAGS_RETURN_MASK = 1,
+ /** Caller does not wait on the packet, EMT will free it. */
+ VMREQFLAGS_NO_WAIT = 2,
+ /** Poke the destination EMT(s) if executing guest code. Use with care. */
+ VMREQFLAGS_POKE = 4,
+ /** Priority request that can safely be processed while doing async
+ * suspend and power off. */
+ VMREQFLAGS_PRIORITY = 8
+} VMREQFLAGS;
+
+
+/**
+ * VM Request packet.
+ *
+ * This is used to request an action in the EMT. Usually the requester is
+ * another thread, but EMT can also end up being the requester in which case
+ * it's carried out synchronously.
+ */
+typedef struct VMREQ
+{
+ /** Pointer to the next request in the chain. */
+ struct VMREQ * volatile pNext;
+ /** Pointer to ring-3 VM structure which this request belongs to. */
+ PUVM pUVM;
+ /** Request state. */
+ volatile VMREQSTATE enmState;
+ /** VBox status code for the completed request. */
+ volatile int32_t iStatus;
+ /** Requester event sem.
+ * The request can use this event semaphore to wait/poll for completion
+ * of the request.
+ */
+ RTSEMEVENT EventSem;
+ /** Set if the event semaphore is clear. */
+ volatile bool fEventSemClear;
+ /** Flags, VMR3REQ_FLAGS_*. */
+ unsigned fFlags;
+ /** Request type. */
+ VMREQTYPE enmType;
+ /** Request destination. */
+ VMCPUID idDstCpu;
+ /** Request specific data. */
+ union VMREQ_U
+ {
+ /** VMREQTYPE_INTERNAL. */
+ struct
+ {
+ /** Pointer to the function to be called. */
+ PFNRT pfn;
+ /** Number of arguments. */
+ unsigned cArgs;
+ /** Array of arguments. */
+ uintptr_t aArgs[64];
+ } Internal;
+ } u;
+} VMREQ;
+/** Pointer to a VM request packet. */
+typedef VMREQ *PVMREQ;
+
+/** @} */
+
+
+#ifndef IN_RC
+/** @defgroup grp_vmm_apis_hc VM Host Context API
+ * @ingroup grp_vm
+ * @{ */
+
+/** @} */
+#endif
+
+
+#ifdef IN_RING3
+/** @defgroup grp_vmm_apis_r3 VM Host Context Ring 3 API
+ * This interface is a _draft_!
+ * @ingroup grp_vm
+ * @{ */
+
+/**
+ * Completion notification codes.
+ */
+typedef enum VMINITCOMPLETED
+{
+ /** The ring-3 init is completed. */
+ VMINITCOMPLETED_RING3 = 1,
+ /** The ring-0 init is completed. */
+ VMINITCOMPLETED_RING0,
+ /** The hardware accelerated virtualization init is completed.
+ * Used to make decisision depending on whether HWACCMIsEnabled(). */
+ VMINITCOMPLETED_HWACCM,
+ /** The GC init is completed. */
+ VMINITCOMPLETED_GC
+} VMINITCOMPLETED;
+
+
+VMMR3DECL(int) VMR3Create(uint32_t cCpus, PCVMM2USERMETHODS pVm2UserCbs,
+ PFNVMATERROR pfnVMAtError, void *pvUserVM,
+ PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM,
+ PVM *ppVM);
+VMMR3DECL(int) VMR3PowerOn(PVM pVM);
+VMMR3DECL(int) VMR3Suspend(PVM pVM);
+VMMR3DECL(int) VMR3Resume(PVM pVM);
+VMMR3DECL(int) VMR3Reset(PVM pVM);
+
+/**
+ * Progress callback.
+ * This will report the completion percentage of an operation.
+ *
+ * @returns VINF_SUCCESS.
+ * @returns Error code to cancel the operation with.
+ * @param pVM The VM handle.
+ * @param uPercent Completion percentage (0-100).
+ * @param pvUser User specified argument.
+ */
+typedef DECLCALLBACK(int) FNVMPROGRESS(PVM pVM, unsigned uPercent, void *pvUser);
+/** Pointer to a FNVMPROGRESS function. */
+typedef FNVMPROGRESS *PFNVMPROGRESS;
+
+VMMR3DECL(int) VMR3Save(PVM pVM, const char *pszFilename, bool fContinueAfterwards, PFNVMPROGRESS pfnProgress, void *pvUser, bool *pfSuspended);
+VMMR3DECL(int) VMR3Teleport(PVM pVM, uint32_t cMsDowntime, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser, PFNVMPROGRESS pfnProgress, void *pvProgressUser, bool *pfSuspended);
+VMMR3DECL(int) VMR3LoadFromFile(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser);
+VMMR3DECL(int) VMR3LoadFromStream(PVM pVM, PCSSMSTRMOPS pStreamOps, void *pvStreamOpsUser,
+ PFNVMPROGRESS pfnProgress, void *pvProgressUser);
+VMMR3DECL(int) VMR3PowerOff(PVM pVM);
+VMMR3DECL(int) VMR3Destroy(PVM pVM);
+VMMR3DECL(void) VMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3DECL(PVM) VMR3EnumVMs(PVM pVMPrev);
+
+VMMR3DECL(PVM) VMR3GetVM(PUVM pUVM);
+VMMR3DECL(PUVM) VMR3GetUVM(PVM pVM);
+VMMR3DECL(uint32_t) VMR3RetainUVM(PUVM pUVM);
+VMMR3DECL(uint32_t) VMR3ReleaseUVM(PUVM pUVM);
+VMMR3DECL(const char *) VMR3GetName(PUVM pUVM);
+VMMR3DECL(PRTUUID) VMR3GetUuid(PUVM pUVM, PRTUUID pUuid);
+VMMR3DECL(VMSTATE) VMR3GetState(PVM pVM);
+VMMR3DECL(VMSTATE) VMR3GetStateU(PUVM pUVM);
+VMMR3DECL(const char *) VMR3GetStateName(VMSTATE enmState);
+
+/**
+ * VM destruction callback.
+ * @param pVM The VM which is about to be destroyed.
+ * @param pvUser The user parameter specified at registration.
+ */
+typedef DECLCALLBACK(void) FNVMATDTOR(PVM pVM, void *pvUser);
+/** Pointer to a VM destruction callback. */
+typedef FNVMATDTOR *PFNVMATDTOR;
+
+VMMR3DECL(int) VMR3AtDtorRegister(PFNVMATDTOR pfnAtDtor, void *pvUser);
+VMMR3DECL(int) VMR3AtDtorDeregister(PFNVMATDTOR pfnAtDtor);
+VMMR3DECL(int) VMR3AtStateRegister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser);
+VMMR3DECL(int) VMR3AtStateDeregister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser);
+VMMR3DECL(bool) VMR3TeleportedAndNotFullyResumedYet(PVM pVM);
+VMMR3DECL(int) VMR3AtErrorRegister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser);
+VMMR3DECL(int) VMR3AtErrorRegisterU(PUVM pVM, PFNVMATERROR pfnAtError, void *pvUser);
+VMMR3DECL(int) VMR3AtErrorDeregister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser);
+VMMR3DECL(void) VMR3SetErrorWorker(PVM pVM);
+VMMR3DECL(uint32_t) VMR3GetErrorCount(PVM pVM);
+VMMR3DECL(uint32_t) VMR3GetErrorCountU(PUVM pUVM);
+VMMR3DECL(int) VMR3AtRuntimeErrorRegister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser);
+VMMR3DECL(int) VMR3AtRuntimeErrorDeregister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser);
+VMMR3DECL(int) VMR3SetRuntimeErrorWorker(PVM pVM);
+VMMR3DECL(uint32_t) VMR3GetRuntimeErrorCount(PVM pVM);
+VMMR3DECL(int) VMR3ReqCall(PVM pVM, VMCPUID idDstCpu, PVMREQ *ppReq, RTMSINTERVAL cMillies, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqCallU(PUVM pUVM, VMCPUID idDstCpu, PVMREQ *ppReq, RTMSINTERVAL cMillies, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqCallVU(PUVM pUVM, VMCPUID idDstCpu, PVMREQ *ppReq, RTMSINTERVAL cMillies, uint32_t fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args);
+VMMR3DECL(int) VMR3ReqCallWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqCallNoWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqCallVoidWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqCallVoidNoWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqPriorityCallWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqPriorityCallVoidWait(PVM pVM, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, ...);
+VMMR3DECL(int) VMR3ReqAlloc(PVM pVM, PVMREQ *ppReq, VMREQTYPE enmType, VMCPUID idDstCpu);
+VMMR3DECL(int) VMR3ReqAllocU(PUVM pUVM, PVMREQ *ppReq, VMREQTYPE enmType, VMCPUID idDstCpu);
+VMMR3DECL(int) VMR3ReqFree(PVMREQ pReq);
+VMMR3DECL(int) VMR3ReqQueue(PVMREQ pReq, RTMSINTERVAL cMillies);
+VMMR3DECL(int) VMR3ReqWait(PVMREQ pReq, RTMSINTERVAL cMillies);
+VMMR3DECL(int) VMR3ReqProcessU(PUVM pUVM, VMCPUID idDstCpu, bool fPriorityOnly);
+VMMR3DECL(void) VMR3NotifyGlobalFFU(PUVM pUVM, uint32_t fFlags);
+VMMR3DECL(void) VMR3NotifyCpuFFU(PUVMCPU pUVMCpu, uint32_t fFlags);
+/** @name Flags for VMR3NotifyCpuFFU and VMR3NotifyGlobalFFU.
+ * @{ */
+/** Whether we've done REM or not. */
+#define VMNOTIFYFF_FLAGS_DONE_REM RT_BIT_32(0)
+/** Whether we should poke the CPU if it's executing guest code. */
+#define VMNOTIFYFF_FLAGS_POKE RT_BIT_32(1)
+/** @} */
+
+VMMR3DECL(int) VMR3WaitHalted(PVM pVM, PVMCPU pVCpu, bool fIgnoreInterrupts);
+VMMR3DECL(int) VMR3WaitU(PUVMCPU pUVMCpu);
+VMMR3_INT_DECL(int) VMR3AsyncPdmNotificationWaitU(PUVMCPU pUVCpu);
+VMMR3_INT_DECL(void) VMR3AsyncPdmNotificationWakeupU(PUVM pUVM);
+VMMR3DECL(RTCPUID) VMR3GetVMCPUId(PVM pVM);
+VMMR3DECL(RTTHREAD) VMR3GetVMCPUThread(PVM pVM);
+VMMR3DECL(RTTHREAD) VMR3GetVMCPUThreadU(PUVM pUVM);
+VMMR3DECL(RTNATIVETHREAD) VMR3GetVMCPUNativeThread(PVM pVM);
+VMMR3DECL(RTNATIVETHREAD) VMR3GetVMCPUNativeThreadU(PUVM pUVM);
+VMMR3DECL(int) VMR3GetCpuCoreAndPackageIdFromCpuId(PVM pVM, VMCPUID idCpu, uint32_t *pidCpuCore, uint32_t *pidCpuPackage);
+VMMR3DECL(int) VMR3HotUnplugCpu(PVM pVM, VMCPUID idCpu);
+VMMR3DECL(int) VMR3HotPlugCpu(PVM pVM, VMCPUID idCpu);
+VMMR3DECL(int) VMR3SetCpuExecutionCap(PVM pVM, uint32_t uCpuExecutionCap);
+/** @} */
+#endif /* IN_RING3 */
+
+
+#ifdef IN_RC
+/** @defgroup grp_vmm_apis_gc VM Guest Context APIs
+ * @ingroup grp_vm
+ * @{ */
+
+/** @} */
+#endif
+
+RT_C_DECLS_END
+
+/** @} */
+
+#endif
+
diff --git a/include/VBox/vmm/vmcpuset.h b/include/VBox/vmm/vmcpuset.h
new file mode 100644
index 00000000..8d92dbb5
--- /dev/null
+++ b/include/VBox/vmm/vmcpuset.h
@@ -0,0 +1,107 @@
+/** @file
+ * VirtualBox - VMCPUSET Operation.
+ */
+
+/*
+ * Copyright (C) 2006-2011 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_vmcpuset_h
+#define ___VBox_vmm_vmcpuset_h
+
+#include <VBox/types.h>
+#include <iprt/asm.h>
+#include <iprt/string.h>
+
+/** @defgroup grp_vmcpuset VMCPUSET Operations
+ * @ingroup grp_types_both
+ * @sa VMCPUSET
+ * @{
+ */
+
+/** Tests if a valid CPU ID is present in the set.. */
+#define VMCPUSET_IS_PRESENT(pSet, idCpu) ASMBitTest( &(pSet)->au32Bitmap[0], (idCpu))
+/** Adds a CPU to the set. */
+#define VMCPUSET_ADD(pSet, idCpu) ASMBitSet( &(pSet)->au32Bitmap[0], (idCpu))
+/** Deletes a CPU from the set. */
+#define VMCPUSET_DEL(pSet, idCpu) ASMBitClear(&(pSet)->au32Bitmap[0], (idCpu))
+/** Empties the set. */
+#define VMCPUSET_EMPTY(pSet) memset(&(pSet)->au32Bitmap[0], '\0', sizeof((pSet)->au32Bitmap))
+/** Fills the set. */
+#define VMCPUSET_FILL(pSet) memset(&(pSet)->au32Bitmap[0], 0xff, sizeof((pSet)->au32Bitmap))
+/** Checks if two sets are equal to one another. */
+#define VMCPUSET_IS_EQUAL(pSet1, pSet2) (memcmp(&(pSet1)->au32Bitmap[0], &(pSet2)->au32Bitmap[0], sizeof((pSet1)->au32Bitmap)) == 0)
+/** Checks if the set is empty. */
+#define VMCPUSET_IS_EMPTY(a_pSet) ( (a_pSet)->au32Bitmap[0] == 0 \
+ && (a_pSet)->au32Bitmap[1] == 0 \
+ && (a_pSet)->au32Bitmap[2] == 0 \
+ && (a_pSet)->au32Bitmap[3] == 0 \
+ && (a_pSet)->au32Bitmap[4] == 0 \
+ && (a_pSet)->au32Bitmap[5] == 0 \
+ && (a_pSet)->au32Bitmap[6] == 0 \
+ && (a_pSet)->au32Bitmap[7] == 0 \
+ )
+/** Finds the first CPU present in the SET.
+ * @returns CPU index if found, NIL_VMCPUID if not. */
+#define VMCPUSET_FIND_FIRST_PRESENT(a_pSet) VMCpuSetFindFirstPresentInternal(a_pSet)
+
+/** Implements VMCPUSET_FIND_FIRST_PRESENT.
+ *
+ * @returns CPU index of the first CPU present in the set, NIL_VMCPUID if none
+ * are present.
+ * @param pSet The set to scan.
+ */
+DECLINLINE(int32_t) VMCpuSetFindFirstPresentInternal(PCVMCPUSET pSet)
+{
+ int i = ASMBitFirstSet(&pSet->au32Bitmap[0], RT_ELEMENTS(pSet->au32Bitmap) * 32);
+ return i >= 0 ? (VMCPUID)i : NIL_VMCPUID;
+}
+
+/** Finds the first CPU present in the SET.
+ * @returns CPU index if found, NIL_VMCPUID if not. */
+#define VMCPUSET_FIND_LAST_PRESENT(a_pSet) VMCpuSetFindLastPresentInternal(a_pSet)
+
+/** Implements VMCPUSET_FIND_LAST_PRESENT.
+ *
+ * @returns CPU index of the last CPU present in the set, NIL_VMCPUID if none
+ * are present.
+ * @param pSet The set to scan.
+ */
+DECLINLINE(int32_t) VMCpuSetFindLastPresentInternal(PCVMCPUSET pSet)
+{
+ uint32_t i = RT_ELEMENTS(pSet->au32Bitmap);
+ while (i-- > 0)
+ {
+ uint32_t u = pSet->au32Bitmap[i];
+ if (u)
+ {
+ u = ASMBitLastSetU32(u);
+ u--;
+ u |= i << 5;
+ return u;
+ }
+ }
+ return NIL_VMCPUID;
+}
+
+/** @ */
+
+#endif
+
diff --git a/include/VBox/vmm/vmm.h b/include/VBox/vmm/vmm.h
new file mode 100644
index 00000000..e3af0c29
--- /dev/null
+++ b/include/VBox/vmm/vmm.h
@@ -0,0 +1,522 @@
+/** @file
+ * VMM - The Virtual Machine Monitor.
+ */
+
+/*
+ * Copyright (C) 2006-2010 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * 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.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+#ifndef ___VBox_vmm_vmm_h
+#define ___VBox_vmm_vmm_h
+
+#include <VBox/types.h>
+#include <VBox/vmm/vmapi.h>
+#include <VBox/sup.h>
+#include <VBox/log.h>
+#include <iprt/stdarg.h>
+
+RT_C_DECLS_BEGIN
+
+/** @defgroup grp_vmm The Virtual Machine Monitor API
+ * @{
+ */
+
+/**
+ * World switcher identifiers.
+ */
+typedef enum VMMSWITCHER
+{
+ /** The usual invalid 0. */
+ VMMSWITCHER_INVALID = 0,
+ /** Switcher for 32-bit host to 32-bit shadow paging. */
+ VMMSWITCHER_32_TO_32,
+ /** Switcher for 32-bit host paging to PAE shadow paging. */
+ VMMSWITCHER_32_TO_PAE,
+ /** Switcher for 32-bit host paging to AMD64 shadow paging. */
+ VMMSWITCHER_32_TO_AMD64,
+ /** Switcher for PAE host to 32-bit shadow paging. */
+ VMMSWITCHER_PAE_TO_32,
+ /** Switcher for PAE host to PAE shadow paging. */
+ VMMSWITCHER_PAE_TO_PAE,
+ /** Switcher for PAE host paging to AMD64 shadow paging. */
+ VMMSWITCHER_PAE_TO_AMD64,
+ /** Switcher for AMD64 host paging to 32-bit shadow paging. */
+ VMMSWITCHER_AMD64_TO_32,
+ /** Switcher for AMD64 host paging to PAE shadow paging. */
+ VMMSWITCHER_AMD64_TO_PAE,
+ /** Switcher for AMD64 host paging to AMD64 shadow paging. */
+ VMMSWITCHER_AMD64_TO_AMD64,
+ /** Used to make a count for array declarations and suchlike. */
+ VMMSWITCHER_MAX,
+ /** The usual 32-bit paranoia. */
+ VMMSWITCHER_32BIT_HACK = 0x7fffffff
+} VMMSWITCHER;
+
+
+/**
+ * VMMRZCallRing3 operations.
+ */
+typedef enum VMMCALLRING3
+{
+ /** Invalid operation. */
+ VMMCALLRING3_INVALID = 0,
+ /** Acquire the PDM lock. */
+ VMMCALLRING3_PDM_LOCK,
+ /** Acquire the critical section specified as argument. */
+ VMMCALLRING3_PDM_CRIT_SECT_ENTER,
+ /** Acquire the PGM lock. */
+ VMMCALLRING3_PGM_LOCK,
+ /** Grow the PGM shadow page pool. */
+ VMMCALLRING3_PGM_POOL_GROW,
+ /** Maps a chunk into ring-3. */
+ VMMCALLRING3_PGM_MAP_CHUNK,
+ /** Allocates more handy pages. */
+ VMMCALLRING3_PGM_ALLOCATE_HANDY_PAGES,
+ /** Allocates a large (2MB) page. */
+ VMMCALLRING3_PGM_ALLOCATE_LARGE_HANDY_PAGE,
+ /** Acquire the MM hypervisor heap lock. */
+ VMMCALLRING3_MMHYPER_LOCK,
+ /** Replay the REM handler notifications. */
+ VMMCALLRING3_REM_REPLAY_HANDLER_NOTIFICATIONS,
+ /** Flush the GC/R0 logger. */
+ VMMCALLRING3_VMM_LOGGER_FLUSH,
+ /** Set the VM error message. */
+ VMMCALLRING3_VM_SET_ERROR,
+ /** Set the VM runtime error message. */
+ VMMCALLRING3_VM_SET_RUNTIME_ERROR,
+ /** Signal a ring 0 assertion. */
+ VMMCALLRING3_VM_R0_ASSERTION,
+ /** Ring switch to force preemption. */
+ VMMCALLRING3_VM_R0_PREEMPT,
+ /** Sync the FTM state with the standby node. */
+ VMMCALLRING3_FTM_SET_CHECKPOINT,
+ /** The usual 32-bit hack. */
+ VMMCALLRING3_32BIT_HACK = 0x7fffffff
+} VMMCALLRING3;
+
+/**
+ * VMMR3AtomicExecuteHandler callback function.
+ *
+ * @returns VBox status code.
+ * @param pVM Pointer to the shared VM structure.
+ * @param pvUser User specified argument
+ *
+ * @todo missing prefix.
+ */
+typedef DECLCALLBACK(int) FNATOMICHANDLER(PVM pVM, void *pvUser);
+/** Pointer to a FNMMATOMICHANDLER(). */
+typedef FNATOMICHANDLER *PFNATOMICHANDLER;
+
+/**
+ * Rendezvous callback.
+ *
+ * @returns VBox strict status code - EM scheduling. Do not return
+ * informational status code other than the ones used by EM for
+ * scheduling.
+ *
+ * @param pVM The VM handle.
+ * @param pVCpu The handle of the calling virtual CPU.
+ * @param pvUser The user argument.
+ */
+typedef DECLCALLBACK(VBOXSTRICTRC) FNVMMEMTRENDEZVOUS(PVM pVM, PVMCPU pVCpu, void *pvUser);
+/** Pointer to a rendezvous callback function. */
+typedef FNVMMEMTRENDEZVOUS *PFNVMMEMTRENDEZVOUS;
+
+/**
+ * Method table that the VMM uses to call back the user of the VMM.
+ */
+typedef struct VMM2USERMETHODS
+{
+ /** Magic value (VMM2USERMETHODS_MAGIC). */
+ uint32_t u32Magic;
+ /** Structure version (VMM2USERMETHODS_VERSION). */
+ uint32_t u32Version;
+
+ /**
+ * Save the VM state.
+ *
+ * @returns VBox status code.
+ * @param pThis Pointer to the callback method table.
+ * @param pUVM The user mode VM handle.
+ *
+ * @remarks This member shall be set to NULL if the operation is not
+ * supported.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnSaveState,(PCVMM2USERMETHODS pThis, PUVM pUVM));
+ /** @todo Move pfnVMAtError and pfnCFGMConstructor here? */
+
+ /**
+ * EMT initialization notification callback.
+ *
+ * This is intended for doing per-thread initialization for EMTs (like COM
+ * init).
+ *
+ * @param pThis Pointer to the callback method table.
+ * @param pUVM The user mode VM handle.
+ * @param pUVCpu The user mode virtual CPU handle.
+ *
+ * @remarks This is optional and shall be set to NULL if not wanted.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnNotifyEmtInit,(PCVMM2USERMETHODS pThis, PUVM pUVM, PUVMCPU pUVCpu));
+
+ /**
+ * EMT termination notification callback.
+ *
+ * This is intended for doing per-thread cleanups for EMTs (like COM).
+ *
+ * @param pThis Pointer to the callback method table.
+ * @param pUVM The user mode VM handle.
+ * @param pUVCpu The user mode virtual CPU handle.
+ *
+ * @remarks This is optional and shall be set to NULL if not wanted.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnNotifyEmtTerm,(PCVMM2USERMETHODS pThis, PUVM pUVM, PUVMCPU pUVCpu));
+
+ /**
+ * PDM thread initialization notification callback.
+ *
+ * This is intended for doing per-thread initialization (like COM init).
+ *
+ * @param pThis Pointer to the callback method table.
+ * @param pUVM The user mode VM handle.
+ *
+ * @remarks This is optional and shall be set to NULL if not wanted.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnNotifyPdmtInit,(PCVMM2USERMETHODS pThis, PUVM pUVM));
+
+ /**
+ * EMT termination notification callback.
+ *
+ * This is intended for doing per-thread cleanups for EMTs (like COM).
+ *
+ * @param pThis Pointer to the callback method table.
+ * @param pUVM The user mode VM handle.
+ *
+ * @remarks This is optional and shall be set to NULL if not wanted.
+ */
+ DECLR3CALLBACKMEMBER(void, pfnNotifyPdmtTerm,(PCVMM2USERMETHODS pThis, PUVM pUVM));
+
+ /** Magic value (VMM2USERMETHODS_MAGIC) marking the end of the structure. */
+ uint32_t u32EndMagic;
+} VMM2USERMETHODS;
+
+/** Magic value of the VMM2USERMETHODS (Franz Kafka). */
+#define VMM2USERMETHODS_MAGIC UINT32_C(0x18830703)
+/** The VMM2USERMETHODS structure version. */
+#define VMM2USERMETHODS_VERSION UINT32_C(0x00020000)
+
+
+VMMDECL(RTRCPTR) VMMGetStackRC(PVMCPU pVCpu);
+VMMDECL(VMCPUID) VMMGetCpuId(PVM pVM);
+VMMDECL(PVMCPU) VMMGetCpu(PVM pVM);
+VMMDECL(PVMCPU) VMMGetCpu0(PVM pVM);
+VMMDECL(PVMCPU) VMMGetCpuById(PVM pVM, VMCPUID idCpu);
+VMMDECL(uint32_t) VMMGetSvnRev(void);
+VMMDECL(VMMSWITCHER) VMMGetSwitcher(PVM pVM);
+VMMDECL(void) VMMTrashVolatileXMMRegs(void);
+
+/** @def VMMIsHwVirtExtForced
+ * Checks if forced to use the hardware assisted virtualization extensions.
+ *
+ * This is intended for making setup decisions where we can save resources when
+ * using hardware assisted virtualization.
+ *
+ * @returns true / false.
+ * @param pVM Pointer to the shared VM structure.
+ */
+#define VMMIsHwVirtExtForced(pVM) ((pVM)->fHwVirtExtForced)
+
+
+#ifdef IN_RING3
+/** @defgroup grp_vmm_r3 The VMM Host Context Ring 3 API
+ * @ingroup grp_vmm
+ * @{
+ */
+VMMR3_INT_DECL(int) VMMR3Init(PVM pVM);
+VMMR3_INT_DECL(int) VMMR3InitR0(PVM pVM);
+VMMR3_INT_DECL(int) VMMR3InitRC(PVM pVM);
+VMMR3_INT_DECL(int) VMMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat);
+VMMR3_INT_DECL(int) VMMR3Term(PVM pVM);
+VMMR3_INT_DECL(void) VMMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
+VMMR3_INT_DECL(int) VMMR3UpdateLoggers(PVM pVM);
+VMMR3DECL(const char *) VMMR3GetRZAssertMsg1(PVM pVM);
+VMMR3DECL(const char *) VMMR3GetRZAssertMsg2(PVM pVM);
+VMMR3_INT_DECL(int) VMMR3GetImportRC(PVM pVM, const char *pszSymbol, PRTRCPTR pRCPtrValue);
+VMMR3_INT_DECL(int) VMMR3SelectSwitcher(PVM pVM, VMMSWITCHER enmSwitcher);
+VMMR3_INT_DECL(int) VMMR3DisableSwitcher(PVM pVM);
+VMMR3_INT_DECL(RTR0PTR) VMMR3GetHostToGuestSwitcher(PVM pVM, VMMSWITCHER enmSwitcher);
+VMMR3_INT_DECL(int) VMMR3RawRunGC(PVM pVM, PVMCPU pVCpu);
+VMMR3_INT_DECL(int) VMMR3HwAccRunGC(PVM pVM, PVMCPU pVCpu);
+VMMR3DECL(int) VMMR3CallRC(PVM pVM, RTRCPTR RCPtrEntry, unsigned cArgs, ...);
+VMMR3DECL(int) VMMR3CallRCV(PVM pVM, RTRCPTR RCPtrEntry, unsigned cArgs, va_list args);
+VMMR3DECL(int) VMMR3CallR0(PVM pVM, uint32_t uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr);
+VMMR3DECL(int) VMMR3ResumeHyper(PVM pVM, PVMCPU pVCpu);
+VMMR3DECL(void) VMMR3FatalDump(PVM pVM, PVMCPU pVCpu, int rcErr);
+VMMR3_INT_DECL(void) VMMR3YieldSuspend(PVM pVM);
+VMMR3_INT_DECL(void) VMMR3YieldStop(PVM pVM);
+VMMR3_INT_DECL(void) VMMR3YieldResume(PVM pVM);
+VMMR3_INT_DECL(void) VMMR3SendSipi(PVM pVM, VMCPUID idCpu, uint32_t uVector);
+VMMR3_INT_DECL(void) VMMR3SendInitIpi(PVM pVM, VMCPUID idCpu);
+VMMR3DECL(int) VMMR3RegisterPatchMemory(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem);
+VMMR3DECL(int) VMMR3DeregisterPatchMemory(PVM pVM, RTGCPTR pPatchMem, unsigned cbPatchMem);
+VMMR3DECL(int) VMMR3EmtRendezvous(PVM pVM, uint32_t fFlags, PFNVMMEMTRENDEZVOUS pfnRendezvous, void *pvUser);
+VMMR3_INT_DECL(bool) VMMR3EmtRendezvousSetDisabled(PVMCPU pVCpu, bool fDisabled);
+/** @defgroup grp_VMMR3EmtRendezvous_fFlags VMMR3EmtRendezvous flags
+ * @{ */
+/** Execution type mask. */
+#define VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK UINT32_C(0x00000007)
+/** Invalid execution type. */
+#define VMMEMTRENDEZVOUS_FLAGS_TYPE_INVALID UINT32_C(0)
+/** Let the EMTs execute the callback one by one (in no particular order). */
+#define VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE UINT32_C(1)
+/** Let all the EMTs execute the callback at the same time. */
+#define VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE UINT32_C(2)
+/** Only execute the callback on one EMT (no particular one). */
+#define VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE UINT32_C(3)
+/** Let the EMTs execute the callback one by one in ascending order. */
+#define VMMEMTRENDEZVOUS_FLAGS_TYPE_ASCENDING UINT32_C(4)
+/** Let the EMTs execute the callback one by one in descending order. */
+#define VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING UINT32_C(5)
+/** Stop after the first error.
+ * This is not valid for any execution type where more than one EMT is active
+ * at a time. */
+#define VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR UINT32_C(0x00000008)
+/** The valid flags. */
+#define VMMEMTRENDEZVOUS_FLAGS_VALID_MASK UINT32_C(0x0000000f)
+/** @} */
+VMMR3_INT_DECL(int) VMMR3EmtRendezvousFF(PVM pVM, PVMCPU pVCpu);
+VMMR3_INT_DECL(int) VMMR3ReadR0Stack(PVM pVM, VMCPUID idCpu, RTHCUINTPTR R0Addr, void *pvBuf, size_t cbRead);
+/** @} */
+#endif /* IN_RING3 */
+
+
+/** @defgroup grp_vmm_r0 The VMM Host Context Ring 0 API
+ * @ingroup grp_vmm
+ * @{
+ */
+
+/**
+ * The VMMR0Entry() codes.
+ */
+typedef enum VMMR0OPERATION
+{
+ /** Run guest context. */
+ VMMR0_DO_RAW_RUN = SUP_VMMR0_DO_RAW_RUN,
+ /** Run guest code using the available hardware acceleration technology. */
+ VMMR0_DO_HWACC_RUN = SUP_VMMR0_DO_HWACC_RUN,
+ /** Official NOP that we use for profiling. */
+ VMMR0_DO_NOP = SUP_VMMR0_DO_NOP,
+ /** Official slow iocl NOP that we use for profiling. */
+ VMMR0_DO_SLOW_NOP,
+
+ /** Ask the GVMM to create a new VM. */
+ VMMR0_DO_GVMM_CREATE_VM,
+ /** Ask the GVMM to destroy the VM. */
+ VMMR0_DO_GVMM_DESTROY_VM,
+ /** Call GVMMR0SchedHalt(). */
+ VMMR0_DO_GVMM_SCHED_HALT,
+ /** Call GVMMR0SchedWakeUp(). */
+ VMMR0_DO_GVMM_SCHED_WAKE_UP,
+ /** Call GVMMR0SchedPoke(). */
+ VMMR0_DO_GVMM_SCHED_POKE,
+ /** Call GVMMR0SchedWakeUpAndPokeCpus(). */
+ VMMR0_DO_GVMM_SCHED_WAKE_UP_AND_POKE_CPUS,
+ /** Call GVMMR0SchedPoll(). */
+ VMMR0_DO_GVMM_SCHED_POLL,
+ /** Call GVMMR0QueryStatistics(). */
+ VMMR0_DO_GVMM_QUERY_STATISTICS,
+ /** Call GVMMR0ResetStatistics(). */
+ VMMR0_DO_GVMM_RESET_STATISTICS,
+ /** Call GVMMR0RegisterVCpu(). */
+ VMMR0_DO_GVMM_REGISTER_VMCPU,
+
+ /** Call VMMR0 Per VM Init. */
+ VMMR0_DO_VMMR0_INIT,
+ /** Call VMMR0 Per VM Termination. */
+ VMMR0_DO_VMMR0_TERM,
+ /** Setup the hardware accelerated raw-mode session. */
+ VMMR0_DO_HWACC_SETUP_VM,
+ /** Attempt to enable or disable hardware accelerated raw-mode. */
+ VMMR0_DO_HWACC_ENABLE,
+ /** Calls function in the hypervisor.
+ * The caller must setup the hypervisor context so the call will be performed.
+ * The difference between VMMR0_DO_RUN_GC and this one is the handling of
+ * the return GC code. The return code will not be interpreted by this operation.
+ */
+ VMMR0_DO_CALL_HYPERVISOR,
+
+ /** Call PGMR0PhysAllocateHandyPages(). */
+ VMMR0_DO_PGM_ALLOCATE_HANDY_PAGES,
+ /** Call PGMR0PhysFlushHandyPages(). */
+ VMMR0_DO_PGM_FLUSH_HANDY_PAGES,
+ /** Call PGMR0AllocateLargePage(). */
+ VMMR0_DO_PGM_ALLOCATE_LARGE_HANDY_PAGE,
+ /** Call PGMR0PhysSetupIommu(). */
+ VMMR0_DO_PGM_PHYS_SETUP_IOMMU,
+
+ /** Call GMMR0InitialReservation(). */
+ VMMR0_DO_GMM_INITIAL_RESERVATION,
+ /** Call GMMR0UpdateReservation(). */
+ VMMR0_DO_GMM_UPDATE_RESERVATION,
+ /** Call GMMR0AllocatePages(). */
+ VMMR0_DO_GMM_ALLOCATE_PAGES,
+ /** Call GMMR0FreePages(). */
+ VMMR0_DO_GMM_FREE_PAGES,
+ /** Call GMMR0FreeLargePage(). */
+ VMMR0_DO_GMM_FREE_LARGE_PAGE,
+ /** Call GMMR0QueryHypervisorMemoryStatsReq(). */
+ VMMR0_DO_GMM_QUERY_HYPERVISOR_MEM_STATS,
+ /** Call GMMR0QueryMemoryStatsReq(). */
+ VMMR0_DO_GMM_QUERY_MEM_STATS,
+ /** Call GMMR0BalloonedPages(). */
+ VMMR0_DO_GMM_BALLOONED_PAGES,
+ /** Call GMMR0MapUnmapChunk(). */
+ VMMR0_DO_GMM_MAP_UNMAP_CHUNK,
+ /** Call GMMR0SeedChunk(). */
+ VMMR0_DO_GMM_SEED_CHUNK,
+ /** Call GMMR0RegisterSharedModule. */
+ VMMR0_DO_GMM_REGISTER_SHARED_MODULE,
+ /** Call GMMR0UnregisterSharedModule. */
+ VMMR0_DO_GMM_UNREGISTER_SHARED_MODULE,
+ /** Call GMMR0ResetSharedModules. */
+ VMMR0_DO_GMM_RESET_SHARED_MODULES,
+ /** Call GMMR0CheckSharedModules. */
+ VMMR0_DO_GMM_CHECK_SHARED_MODULES,
+ /** Call GMMR0FindDuplicatePage. */
+ VMMR0_DO_GMM_FIND_DUPLICATE_PAGE,
+ /** Call GMMR0QueryStatistics(). */
+ VMMR0_DO_GMM_QUERY_STATISTICS,
+ /** Call GMMR0ResetStatistics(). */
+ VMMR0_DO_GMM_RESET_STATISTICS,
+
+ /** Set a GVMM or GMM configuration value. */
+ VMMR0_DO_GCFGM_SET_VALUE,
+ /** Query a GVMM or GMM configuration value. */
+ VMMR0_DO_GCFGM_QUERY_VALUE,
+
+ /** Call PDMR0DriverCallReqHandler. */
+ VMMR0_DO_PDM_DRIVER_CALL_REQ_HANDLER,
+ /** Call PDMR0DeviceCallReqHandler. */
+ VMMR0_DO_PDM_DEVICE_CALL_REQ_HANDLER,
+
+ /** The start of the R0 service operations. */
+ VMMR0_DO_SRV_START,
+ /** Call IntNetR0Open(). */
+ VMMR0_DO_INTNET_OPEN,
+ /** Call IntNetR0IfClose(). */
+ VMMR0_DO_INTNET_IF_CLOSE,
+ /** Call IntNetR0IfGetBufferPtrs(). */
+ VMMR0_DO_INTNET_IF_GET_BUFFER_PTRS,
+ /** Call IntNetR0IfSetPromiscuousMode(). */
+ VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE,
+ /** Call IntNetR0IfSetMacAddress(). */
+ VMMR0_DO_INTNET_IF_SET_MAC_ADDRESS,
+ /** Call IntNetR0IfSetActive(). */
+ VMMR0_DO_INTNET_IF_SET_ACTIVE,
+ /** Call IntNetR0IfSend(). */
+ VMMR0_DO_INTNET_IF_SEND,
+ /** Call IntNetR0IfWait(). */
+ VMMR0_DO_INTNET_IF_WAIT,
+ /** Call IntNetR0IfAbortWait(). */
+ VMMR0_DO_INTNET_IF_ABORT_WAIT,
+
+ /** Forward call to the PCI driver */
+ VMMR0_DO_PCIRAW_REQ,
+
+ /** The end of the R0 service operations. */
+ VMMR0_DO_SRV_END,
+
+ /** Official call we use for testing Ring-0 APIs. */
+ VMMR0_DO_TESTS,
+ /** Test the 32->64 bits switcher. */
+ VMMR0_DO_TEST_SWITCHER3264,
+
+ /** The usual 32-bit type blow up. */
+ VMMR0_DO_32BIT_HACK = 0x7fffffff
+} VMMR0OPERATION;
+
+
+/**
+ * Request buffer for VMMR0_DO_GCFGM_SET_VALUE and VMMR0_DO_GCFGM_QUERY_VALUE.
+ * @todo Move got GCFGM.h when it's implemented.
+ */
+typedef struct GCFGMVALUEREQ
+{
+ /** The request header.*/
+ SUPVMMR0REQHDR Hdr;
+ /** The support driver session handle. */
+ PSUPDRVSESSION pSession;
+ /** The value.
+ * This is input for the set request and output for the query. */
+ uint64_t u64Value;
+ /** The variable name.
+ * This is fixed sized just to make things simple for the mock-up. */
+ char szName[48];
+} GCFGMVALUEREQ;
+/** Pointer to a VMMR0_DO_GCFGM_SET_VALUE and VMMR0_DO_GCFGM_QUERY_VALUE request buffer.
+ * @todo Move got GCFGM.h when it's implemented.
+ */
+typedef GCFGMVALUEREQ *PGCFGMVALUEREQ;
+
+VMMR0DECL(int) VMMR0EntryInt(PVM pVM, VMMR0OPERATION enmOperation, void *pvArg);
+VMMR0DECL(void) VMMR0EntryFast(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation);
+VMMR0DECL(int) VMMR0EntryEx(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION);
+VMMR0DECL(int) VMMR0TermVM(PVM pVM, PGVM pGVM);
+
+#ifdef LOG_ENABLED
+VMMR0DECL(void) VMMR0LogFlushDisable(PVMCPU pVCpu);
+VMMR0DECL(void) VMMR0LogFlushEnable(PVMCPU pVCpu);
+#else
+#define VMMR0LogFlushDisable(pVCpu) do { } while(0)
+#define VMMR0LogFlushEnable(pVCpu) do { } while(0)
+#endif
+
+/** @} */
+
+
+#ifdef IN_RC
+/** @defgroup grp_vmm_rc The VMM Raw-Mode Context API
+ * @ingroup grp_vmm
+ * @{
+ */
+VMMRCDECL(int) VMMGCEntry(PVM pVM, unsigned uOperation, unsigned uArg, ...);
+VMMRCDECL(void) VMMGCGuestToHost(PVM pVM, int rc);
+VMMRCDECL(void) VMMGCLogFlushIfFull(PVM pVM);
+/** @} */
+#endif /* IN_RC */
+
+#if defined(IN_RC) || defined(IN_RING0)
+/** @defgroup grp_vmm_rz The VMM Raw-Mode and Ring-0 Context API
+ * @ingroup grp_vmm
+ * @{
+ */
+VMMRZDECL(int) VMMRZCallRing3(PVM pVM, PVMCPU pVCpu, VMMCALLRING3 enmOperation, uint64_t uArg);
+VMMRZDECL(int) VMMRZCallRing3NoCpu(PVM pVM, VMMCALLRING3 enmOperation, uint64_t uArg);
+VMMRZDECL(void) VMMRZCallRing3Disable(PVMCPU pVCpu);
+VMMRZDECL(void) VMMRZCallRing3Enable(PVMCPU pVCpu);
+VMMRZDECL(bool) VMMRZCallRing3IsEnabled(PVMCPU pVCpu);
+/** @} */
+#endif
+
+
+/** @} */
+RT_C_DECLS_END
+
+#endif