summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/testcase
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/testcase')
-rw-r--r--src/VBox/Devices/testcase/Makefile.kmk157
-rw-r--r--src/VBox/Devices/testcase/tstDevice.cpp1043
-rw-r--r--src/VBox/Devices/testcase/tstDeviceBuiltin.h47
-rw-r--r--src/VBox/Devices/testcase/tstDeviceCfg.cpp560
-rw-r--r--src/VBox/Devices/testcase/tstDeviceCfg.h169
-rw-r--r--src/VBox/Devices/testcase/tstDeviceInternal.h578
-rw-r--r--src/VBox/Devices/testcase/tstDeviceIoFuzz.cpp269
-rw-r--r--src/VBox/Devices/testcase/tstDevicePdmDevHlp.cpp6196
-rw-r--r--src/VBox/Devices/testcase/tstDevicePdmDevHlpR0.cpp1523
-rw-r--r--src/VBox/Devices/testcase/tstDevicePdmThread.cpp996
-rw-r--r--src/VBox/Devices/testcase/tstDevicePlugin.h100
-rw-r--r--src/VBox/Devices/testcase/tstDeviceR0.cpp163
-rw-r--r--src/VBox/Devices/testcase/tstDeviceSsmFuzz.cpp200
-rw-r--r--src/VBox/Devices/testcase/tstDeviceSsmLoadDbg.cpp159
-rw-r--r--src/VBox/Devices/testcase/tstDeviceStructSize.cpp454
-rw-r--r--src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp2264
16 files changed, 14878 insertions, 0 deletions
diff --git a/src/VBox/Devices/testcase/Makefile.kmk b/src/VBox/Devices/testcase/Makefile.kmk
new file mode 100644
index 00000000..a65768b8
--- /dev/null
+++ b/src/VBox/Devices/testcase/Makefile.kmk
@@ -0,0 +1,157 @@
+# $Id: Makefile.kmk $
+## @file
+# Sub-Makefile for the device testcases.
+#
+
+#
+# Copyright (C) 2006-2023 Oracle and/or its affiliates.
+#
+# This file is part of VirtualBox base platform packages, as
+# available from https://www.virtualbox.org.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation, in version 3 of the
+# License.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses>.
+#
+# SPDX-License-Identifier: GPL-3.0-only
+#
+
+SUB_DEPTH = ../../../..
+include $(KBUILD_PATH)/subheader.kmk
+
+#
+# Globals
+#
+VBOX_PATH_DEVICES_SRC ?= $(PATH_ROOT)/src/VBox/Devices
+VBOX_PATH_VMM_DEVICES_SRC ?= $(PATH_ROOT)/src/VBox/VMM/include
+VBOX_DEVICES_TEST_OUT_DIR := $(PATH_TARGET)/Devices/testcase
+BLDDIRS += $(VBOX_DEVICES_TEST_OUT_DIR)
+
+VBOX_DEVICES_TESTS_FEATURES = \
+ $(if $(VBOX_WITH_AHCI),VBOX_WITH_AHCI,) \
+ $(if $(VBOX_WITH_BUSLOGIC),VBOX_WITH_BUSLOGIC,) \
+ $(if $(VBOX_WITH_E1000),VBOX_WITH_E1000,) \
+ $(if $(VBOX_WITH_EHCI_IMPL),VBOX_WITH_EHCI_IMPL,) \
+ $(if $(VBOX_WITH_HGSMI),VBOX_WITH_HGSMI,) \
+ $(if $(VBOX_WITH_HP_HDA),VBOX_WITH_HP_HDA,) \
+ $(if $(VBOX_WITH_INTEL_HDA),VBOX_WITH_INTEL_HDA,) \
+ $(if $(VBOX_WITH_NVIDIA_HDA),VBOX_WITH_NVIDIA_HDA,) \
+ $(if $(VBOX_WITH_LSILOGIC),VBOX_WITH_LSILOGIC,) \
+ $(if $(VBOX_WITH_NVME_IMPL),VBOX_WITH_NVME_IMPL,) \
+ $(if $(VBOX_WITH_PCI_PASSTHROUGH_IMPL),VBOX_WITH_PCI_PASSTHROUGH_IMPL,) \
+ $(if $(VBOX_WITH_RAW_MODE),VBOX_WITH_RAW_MODE,) \
+ $(if $(VBOX_WITH_SCSI),VBOX_WITH_SCSI,) \
+ $(if $(VBOX_WITH_USB),VBOX_WITH_USB,) \
+ $(if $(VBOX_WITH_VDMA),VBOX_WITH_VDMA,) \
+ $(if $(VBOX_WITH_VIDEOHWACCEL),VBOX_WITH_VIDEOHWACCEL,) \
+ $(if $(VBOX_WITH_VIRTIO),VBOX_WITH_VIRTIO,) \
+ $(if $(VBOX_WITH_VMSVGA),VBOX_WITH_VMSVGA,) \
+ $(if $(VBOX_WITH_WDDM),VBOX_WITH_WDDM,) \
+ $(if $(VBOX_WITH_XHCI_IMPL),VBOX_WITH_XHCI_IMPL,) \
+ $(if $(VBOX_WITH_IOMMU_AMD),VBOX_WITH_IOMMU_AMD,) \
+ $(if $(VBOX_WITH_IOMMU_INTEL),VBOX_WITH_IOMMU_INTEL,) \
+ $(VBOX_AUDIO_DEFS) \
+ $(VMM_COMMON_DEFS)
+
+#
+# We setup one 'other' target for executing the structure & alignment
+# validation testcases. Perhaps a bit hackish, but extremely useful.
+#
+ifeq ($(KBUILD_TARGET),$(KBUILD_HOST))
+ ifeq ($(filter-out x86.x86 amd64.amd64 x86.amd64, $(KBUILD_TARGET_ARCH).$(KBUILD_HOST_ARCH)),)
+ OTHERS += \
+ $(VBOX_DEVICES_TEST_OUT_DIR)/tstDeviceStructSize.run
+ endif
+endif
+
+# The normal testing pass.
+TESTING += \
+ $(VBOX_DEVICES_TEST_OUT_DIR)/tstDeviceStructSize.run
+
+ifdef VBOX_WITH_RAW_MODE
+ #
+ # The testcase generator.
+ #
+ PROGRAMS += tstDeviceStructSizeRC
+ tstDeviceStructSizeRC_TEMPLATE = VBoxRcExe
+ tstDeviceStructSizeRC_DEFS = $(VBOX_DEVICES_TESTS_FEATURES)
+ tstDeviceStructSizeRC_SOURCES = tstDeviceStructSizeRC.cpp
+ tstDeviceStructSizeRC_INCS = \
+ $(VBOX_PATH_DEVICES_SRC)/build \
+ $(VBOX_PATH_DEVICES_SRC)/Bus \
+ $(VBOX_DEVICES_TEST_OUT_DIR) \
+ $(VBOX_GRAPHICS_INCS)
+ tstDeviceStructSizeRC_INCS += $(VBOX_PATH_VMM_DEVICES_SRC)
+endif # VBOX_WITH_RAW_MODE
+
+#
+# The testcase it self.
+#
+PROGRAMS += tstDeviceStructSize
+if "$(KBUILD_TARGET)" != "win" && $(VBOX_GCC_VERSION_CXX) < 40600
+ #
+ # Disable "ISO C++ prohibits anonymous structs [-Werror=pedantic]" caused by Mesa VMSVGA driver headers
+ # For GCC >= 4.6.0 the warning is disabled in DevVGA_SVGA.h
+ #
+ # Template used for gcc older than 4.6. (Strips away compiler options.)
+ #
+ TEMPLATE_tstDeviceStructSizeOldGCC := tstDeviceStructSizeOldGCC
+ TEMPLATE_tstDeviceStructSizeOldGCC_EXTENDS := VBoxR3AutoTest
+ TEMPLATE_tstDeviceStructSizeOldGCC_CXXFLAGS = $(filter-out -pedantic,$(TEMPLATE_$(TEMPLATE_tstDeviceStructSizeOldGCC_EXTENDS)_CXXFLAGS))
+
+ tstDeviceStructSize_TEMPLATE = tstDeviceStructSizeOldGCC
+else
+ tstDeviceStructSize_TEMPLATE = VBoxR3AutoTest
+endif
+tstDeviceStructSize_DEFS = $(VBOX_DEVICES_TESTS_FEATURES)
+tstDeviceStructSize_INCS = \
+ $(VBOX_PATH_DEVICES_SRC)/build \
+ $(VBOX_PATH_DEVICES_SRC)/Bus \
+ $(VBOX_DEVICES_TEST_OUT_DIR) \
+ $(VBOX_GRAPHICS_INCS) \
+ $(VBOX_PATH_VMSVGA_DEVICE_INC)
+tstDeviceStructSize_SOURCES = tstDeviceStructSize.cpp
+tstDeviceStructSize_CLEAN = \
+ $(VBOX_DEVICES_TEST_OUT_DIR)/tstDeviceStructSizeRC.h \
+ $(VBOX_DEVICES_TEST_OUT_DIR)/tstDeviceStructSize.run
+ifdef VBOX_WITH_RAW_MODE
+ tstDeviceStructSize.cpp_DEPS = $(VBOX_DEVICES_TEST_OUT_DIR)/tstDeviceStructSizeRC.h
+endif
+tstDeviceStructSize_INCS += $(VBOX_PATH_VMM_DEVICES_SRC)
+
+#
+# Run rule for tstDeviceStructSize.
+#
+
+# 1. Dump selected structure in the VMMRC.rc debug info.
+# 2. Generate a testcase from the dump
+## future
+
+ifdef VBOX_WITH_RAW_MODE
+ # 1&2. Manually dump selected structures and members.
+ $(VBOX_DEVICES_TEST_OUT_DIR)/tstDeviceStructSizeRC.h: $$(tstDeviceStructSizeRC_1_STAGE_TARGET) | $$(dir $$@)
+ $(call MSG_GENERATE,,$@)
+ $(QUIET)$(REDIRECT) -wo $@ -- $^
+endif
+
+# 3. run it.
+$(VBOX_DEVICES_TEST_OUT_DIR)/tstDeviceStructSize.run: $$(tstDeviceStructSize_1_STAGE_TARGET) | $$(dir $$@)
+ $(QUIET)$(RM) -f $@
+ $^
+ $(QUIET)$(APPEND) "$@" "done"
+
+# alias for the struct test.
+run-struct-tests: $(VBOX_DEVICES_TEST_OUT_DIR)/tstDeviceStructSize.run
+
+
+include $(FILE_KBUILD_SUB_FOOTER)
+
diff --git a/src/VBox/Devices/testcase/tstDevice.cpp b/src/VBox/Devices/testcase/tstDevice.cpp
new file mode 100644
index 00000000..a4d93002
--- /dev/null
+++ b/src/VBox/Devices/testcase/tstDevice.cpp
@@ -0,0 +1,1043 @@
+/* $Id: tstDevice.cpp $ */
+/** @file
+ * tstDevice - Test framework for PDM devices/drivers
+ */
+
+/*
+ * Copyright (C) 2017-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEFAULT /** @todo */
+#include <VBox/types.h>
+#include <VBox/sup.h>
+#include <VBox/version.h>
+#include <iprt/assert.h>
+#include <iprt/ctype.h>
+#include <iprt/getopt.h>
+#include <iprt/initterm.h>
+#include <iprt/ldr.h>
+#include <iprt/log.h>
+#include <iprt/list.h>
+#include <iprt/mem.h>
+#include <iprt/once.h>
+#include <iprt/path.h>
+#include <iprt/string.h>
+#include <iprt/stream.h>
+#include <iprt/trace.h>
+
+#include "tstDeviceInternal.h"
+#include "tstDeviceCfg.h"
+#include "tstDeviceBuiltin.h"
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+
+#define PDM_MAX_DEVICE_INSTANCE_SIZE _4M
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+
+
+/**
+ * Testcase plugin descriptor.
+ */
+typedef struct TSTDEVPLUGIN
+{
+ /** Node for the plugin list. */
+ RTLISTNODE NdPlugins;
+ /** Copy of the filename. */
+ char *pszFilename;
+ /** Loader handle. */
+ RTLDRMOD hMod;
+ /** Number of references to this plugin. */
+ volatile uint32_t cRefs;
+} TSTDEVPLUGIN;
+/** Pointer to a device plugin descriptor. */
+typedef TSTDEVPLUGIN *PTSTDEVPLUGIN;
+/** Pointer to a const plugin descriptor. */
+typedef const TSTDEVPLUGIN *PCTSTDEVPLUGIN;
+
+
+/**
+ * Testcase descriptor.
+ */
+typedef struct TSTDEVTESTCASE
+{
+ /** Node for the list of registered testcases. */
+ RTLISTNODE NdTestcases;
+ /** Pointer to the plugin the testcase belongs to. */
+ PCTSTDEVPLUGIN pPlugin;
+ /** Pointer to the testcase descriptor. */
+ PCTSTDEVTESTCASEREG pTestcaseReg;
+} TSTDEVTESTCASE;
+/** Pointer to a testcase descriptor. */
+typedef TSTDEVTESTCASE *PTSTDEVTESTCASE;
+/** Pointer to a constant testcase descriptor. */
+typedef const TSTDEVTESTCASE *PCTSTDEVTESTCASE;
+
+
+/**
+ * PDM R0/RC module trampoline descriptor.
+ */
+#pragma pack(1)
+typedef struct TSTDEVPDMMODTRAMPOLINE
+{
+ /** Jump instruction. */
+ uint8_t abJmp[6];
+ /** Address to jump to. */
+ uintptr_t AddrTarget;
+ /** Padding to get a 16byte aligned structure. */
+ uint8_t abPadding[HC_ARCH_BITS == 64 ? 2 : 5];
+} TSTDEVPDMMODTRAMPOLINE;
+#pragma pack()
+AssertCompileSize(TSTDEVPDMMODTRAMPOLINE, 16);
+/** Pointer to a trampoline descriptor. */
+typedef TSTDEVPDMMODTRAMPOLINE *PTSTDEVPDMMODTRAMPOLINE;
+
+/**
+ * PDM module descriptor.
+ */
+typedef struct TSTDEVPDMMOD
+{
+ /** Node for the module list. */
+ RTLISTNODE NdPdmMods;
+ /** Type of module (R3/R0/RC). */
+ TSTDEVPDMMODTYPE enmType;
+ /** Copy of the filename. */
+ char *pszFilename;
+ /** Loader handle. */
+ RTLDRMOD hLdrMod;
+ /** Number of references to this plugin. */
+ volatile uint32_t cRefs;
+ /** R0/RC Module type dependent data. */
+ struct
+ {
+ /** The exectuable image bits. */
+ void *pvBits;
+ /** Size of the memory buffer. */
+ size_t cbBits;
+ /** Pointer to the executable memory containing the trampoline code. */
+ uint8_t *pbTrampoline;
+ /** Number of trampoline entries supported. */
+ uint32_t cTrampolinesMax;
+ /** Number of trampoline entries used. */
+ uint32_t cTrampolines;
+ /** Pointer to the next unused trampoline entry. */
+ PTSTDEVPDMMODTRAMPOLINE pTrampolineNext;
+ } R0Rc;
+} TSTDEVPDMMOD;
+/** Pointer to a PDM module descriptor. */
+typedef TSTDEVPDMMOD *PTSTDEVPDMMOD;
+
+
+/**
+ * Internal callback structure pointer.
+ * The main purpose is to define the extra data we associate
+ * with PDMDEVREGCB so we can find the plugin the device is associated with etc.
+ */
+typedef struct TSTDEVPDMDEVREGCBINT
+{
+ /** The callback structure. */
+ PDMDEVREGCB Core;
+ /** A bit of padding. */
+ uint32_t u32[4];
+ /** Pointer to plugin. */
+ PTSTDEVPDMMOD pMod;
+} TSTDEVPDMDEVREGCBINT;
+/** Pointer to a PDMDEVREGCBINT structure. */
+typedef TSTDEVPDMDEVREGCBINT *PTSTDEVPDMDEVREGCBINT;
+/** Pointer to a const PDMDEVREGCBINT structure. */
+typedef const TSTDEVPDMDEVREGCBINT *PCTSTDEVPDMDEVREGCBINT;
+
+
+typedef struct TSTDEVPDMR0IMPORTS
+{
+ /** The symbol name. */
+ const char *pszSymbol;
+ /** The pointer. */
+ PFNRT pfn;
+} TSTDEVPDMR0IMPORTS;
+typedef const TSTDEVPDMR0IMPORTS *PCTSTDEVPDMR0IMPORTS;
+
+typedef DECLCALLBACKTYPE(int, FNR0MODULEINIT,(void *hMod));
+typedef FNR0MODULEINIT *PFNR0MODULEINIT;
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+/** List of registered testcase plugins. */
+RTLISTANCHOR g_LstPlugins;
+/** List of registered testcases. */
+RTLISTANCHOR g_LstTestcases;
+/** List of registered PDM modules. */
+RTLISTANCHOR g_LstPdmMods;
+/** List of registered PDM R0 modules. */
+RTLISTANCHOR g_LstPdmR0Mods;
+/** List of registered PDM devices. */
+RTLISTANCHOR g_LstPdmDevs;
+
+static int tstDevPdmR0RegisterModule(void *hMod, PPDMDEVMODREGR0 pModReg);
+
+/**
+ * PDM R0 imports we implement.
+ */
+static const TSTDEVPDMR0IMPORTS g_aPdmR0Imports[] =
+{
+ {"SUPR0TracerFireProbe", (PFNRT)NULL},
+ {"SUPSemEventSignal", (PFNRT)NULL},
+ {"PDMR0DeviceRegisterModule", (PFNRT)tstDevPdmR0RegisterModule},
+ {"PDMR0DeviceDeregisterModule", (PFNRT)NULL},
+ {"PGMShwMakePageWritable", (PFNRT)NULL},
+ {"IntNetR0IfSend", (PFNRT)/*IntNetR0IfSend*/NULL},
+ {"IntNetR0IfSetPromiscuousMode", (PFNRT)/*IntNetR0IfSetPromiscuousMode*/NULL},
+ {"RTAssertMsg1Weak", (PFNRT)RTAssertMsg1Weak},
+ {"RTAssertMsg2Weak", (PFNRT)RTAssertMsg2Weak},
+ {"RTAssertShouldPanic", (PFNRT)RTAssertShouldPanic},
+ {"RTLogDefaultInstanceEx", (PFNRT)RTLogDefaultInstanceEx},
+ {"RTLogLoggerEx", (PFNRT)RTLogLoggerEx},
+ {"RTLogRelGetDefaultInstanceEx", (PFNRT)RTLogRelGetDefaultInstanceEx},
+ {"RTOnceSlow", (PFNRT)RTOnceSlow},
+ {"RTR0AssertPanicSystem", (PFNRT)0x10101010},
+ {"RTThreadSleep", (PFNRT)RTThreadSleep},
+ {"RTTimeMilliTS", (PFNRT)RTTimeMilliTS},
+ {"RTTimeNanoTS", (PFNRT)RTTimeNanoTS},
+ {"RTTraceBufAddMsgF", (PFNRT)RTTraceBufAddMsgF},
+ {"RTMemAllocZTag", (PFNRT)RTMemAllocZTag},
+ {"RTMemFree", (PFNRT)RTMemFree},
+ {"RTStrPrintf", (PFNRT)RTStrPrintf},
+ {"nocrt_memcmp", (PFNRT)memcmp},
+ {"nocrt_memcpy", (PFNRT)memcpy},
+ {"nocrt_memmove", (PFNRT)memmove},
+ {"nocrt_memset", (PFNRT)memset},
+ {"nocrt_strlen", (PFNRT)strlen},
+};
+
+
+/*********************************************************************************************************************************
+* Internal Functions *
+*********************************************************************************************************************************/
+
+#if 0
+/**
+ * Parses the options given to the testcase.
+ *
+ * @returns Process status code.
+ * @param cArgs Number of arguments given.
+ * @param paszArgs Pointer to the argument vector.
+ */
+static RTEXITCODE tstDevParseOptions(int cArgs, char *paszArgs[])
+{
+ static RTGETOPTDEF const s_aOptions[] =
+ {
+ };
+
+
+ int ch;
+ RTGETOPTUNION Value;
+ RTGETOPTSTATE GetState;
+ RTGetOptInit(&GetState, argc, argv, s_aOptions, RT_ELEMENTS(s_aOptions), 1, 0 /* fFlags */);
+ while ((ch = RTGetOpt(&GetState, &Value)))
+ {
+ switch (ch)
+ {
+ default:
+ return RTGetOptPrintError(ch, &Value);
+ }
+ }
+}
+#endif
+
+
+/**
+ * Checks whether the given testcase name is already existing.
+ *
+ * @returns Pointer to existing testcase, NULL if not found.
+ * @param pszFilename The filename to check.
+ */
+static PCTSTDEVTESTCASE tstDevTestcaseFind(const char *pszName)
+{
+ PCTSTDEVTESTCASE pIt;
+ RTListForEach(&g_LstTestcases, pIt, TSTDEVTESTCASE, NdTestcases)
+ {
+ if (!RTStrCmp(pIt->pTestcaseReg->szName, pszName))
+ return pIt;
+ }
+
+ return NULL;
+}
+
+
+/**
+ * @interface_method_impl{TSTDEVPLUGINREGISTER,pfnRegisterTestcase}
+ */
+static DECLCALLBACK(int) tstDevRegisterTestcase(void *pvUser, PCTSTDEVTESTCASEREG pTestcaseReg)
+{
+ int rc = VINF_SUCCESS;
+ PTSTDEVPLUGIN pPlugin = (PTSTDEVPLUGIN)pvUser;
+
+ /* Try to find a testcase with the name first. */
+ if (!tstDevTestcaseFind(pTestcaseReg->szName))
+ {
+ PTSTDEVTESTCASE pTestcase = (PTSTDEVTESTCASE)RTMemAllocZ(sizeof(TSTDEVPLUGIN));
+ if (RT_LIKELY(pTestcase))
+ {
+ pTestcase->pPlugin = pPlugin;
+ if (pPlugin)
+ pPlugin->cRefs++;
+ pTestcase->pTestcaseReg = pTestcaseReg;
+ RTListAppend(&g_LstTestcases, &pTestcase->NdTestcases);
+ return VINF_SUCCESS;
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+ else
+ rc = VERR_ALREADY_EXISTS;
+
+ return rc;
+}
+
+
+/**
+ * Checks whether the given plugin filename was already loaded.
+ *
+ * @returns Pointer to already loaded plugin, NULL if not found.
+ * @param pszFilename The filename to check.
+ */
+static PCTSTDEVPLUGIN tstDevPluginFind(const char *pszFilename)
+{
+ PCTSTDEVPLUGIN pIt;
+ RTListForEach(&g_LstPlugins, pIt, TSTDEVPLUGIN, NdPlugins)
+ {
+ if (!RTStrCmp(pIt->pszFilename, pszFilename))
+ return pIt;
+ }
+
+ return NULL;
+}
+
+
+/**
+ * Tries to loads the given plugin.
+ *
+ * @returns VBox status code.
+ * @param pszFilename The filename to load.
+ */
+static int tstDevLoadPlugin(const char *pszFilename)
+{
+ int rc = VINF_SUCCESS;
+
+ /* Check whether the plugin is loaded first. */
+ if (!tstDevPluginFind(pszFilename))
+ {
+ PTSTDEVPLUGIN pPlugin = (PTSTDEVPLUGIN)RTMemAllocZ(sizeof(TSTDEVPLUGIN));
+ if (RT_LIKELY(pPlugin))
+ {
+ pPlugin->pszFilename = RTStrDup(pszFilename);
+ pPlugin->cRefs = 1;
+ rc = RTLdrLoad(pszFilename, &pPlugin->hMod);
+ if (RT_SUCCESS(rc))
+ {
+ TSTDEVPLUGINREGISTER TestcaseRegister;
+ PFNTSTDEVPLUGINLOAD pfnPluginLoad = NULL;
+
+ TestcaseRegister.pfnRegisterTestcase = tstDevRegisterTestcase;
+
+ rc = RTLdrGetSymbol(pPlugin->hMod, TSTDEV_PLUGIN_LOAD_NAME, (void**)&pfnPluginLoad);
+ if (RT_FAILURE(rc) || !pfnPluginLoad)
+ {
+ LogFunc(("error resolving the entry point %s in plugin %s, rc=%Rrc, pfnPluginLoad=%#p\n",
+ TSTDEV_PLUGIN_LOAD_NAME, pszFilename, rc, pfnPluginLoad));
+ if (RT_SUCCESS(rc))
+ rc = VERR_SYMBOL_NOT_FOUND;
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ /* Get the function table. */
+ rc = pfnPluginLoad(pPlugin, &TestcaseRegister);
+ }
+ else
+ LogFunc(("ignored plugin '%s': rc=%Rrc\n", pszFilename, rc));
+
+ /* Create a plugin entry on success. */
+ if (RT_SUCCESS(rc))
+ {
+ RTListAppend(&g_LstPlugins, &pPlugin->NdPlugins);
+ return VINF_SUCCESS;
+ }
+ else
+ RTLdrClose(pPlugin->hMod);
+ }
+
+ RTMemFree(pPlugin);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+
+ return rc;
+}
+
+
+/**
+ * Checks whether the given testcase name is already existing.
+ *
+ * @returns Pointer to already loaded plugin, NULL if not found.
+ * @param pszFilename The filename to check.
+ * @param ppR0Reg Where to store the pointer to the R0 registration record
+ * if existing, optional.
+ */
+DECLHIDDEN(PCTSTDEVPDMDEV) tstDevPdmDeviceFind(const char *pszName, PCPDMDEVREGR0 *ppR0Reg)
+{
+ PCTSTDEVPDMDEV pIt;
+ RTListForEach(&g_LstPdmDevs, pIt, TSTDEVPDMDEV, NdPdmDevs)
+ {
+ if (!RTStrCmp(pIt->pReg->szName, pszName))
+ {
+ if (ppR0Reg)
+ {
+ *ppR0Reg = NULL;
+
+ PPDMDEVMODREGR0 pItR0;
+ RTListForEach(&g_LstPdmR0Mods, pItR0, PDMDEVMODREGR0, ListEntry)
+ {
+ for (uint32_t i = 0; i < pItR0->cDevRegs; i++)
+ {
+ PCPDMDEVREGR0 pReg = pItR0->papDevRegs[i];
+ if (!RTStrCmp(pReg->szName, pszName))
+ {
+ *ppR0Reg = pReg;
+ return pIt;
+ }
+ }
+ }
+ }
+
+ return pIt;
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * Checks that a PDMDRVREG::szName, PDMDEVREG::szName or PDMUSBREG::szName
+ * field contains only a limited set of ASCII characters.
+ *
+ * @returns true / false.
+ * @param pszName The name to validate.
+ */
+bool tstDevPdmR3IsValidName(const char *pszName)
+{
+ char ch;
+ while ( (ch = *pszName) != '\0'
+ && ( RT_C_IS_ALNUM(ch)
+ || ch == '-'
+ || ch == ' ' /** @todo disallow this! */
+ || ch == '_') )
+ pszName++;
+ return ch == '\0';
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVREGCB,pfnRegister}
+ */
+static DECLCALLBACK(int) tstDevPdmR3DevReg_Register(PPDMDEVREGCB pCallbacks, PCPDMDEVREG pReg)
+{
+ /*
+ * Validate the registration structure (mostly copy and paste from PDMDevice.cpp).
+ */
+ Assert(pReg);
+ AssertMsgReturn(pReg->u32Version == PDM_DEVREG_VERSION,
+ ("Unknown struct version %#x!\n", pReg->u32Version),
+ VERR_PDM_UNKNOWN_DEVREG_VERSION);
+
+ AssertMsgReturn( pReg->szName[0]
+ && strlen(pReg->szName) < sizeof(pReg->szName)
+ && tstDevPdmR3IsValidName(pReg->szName),
+ ("Invalid name '%.*s'\n", sizeof(pReg->szName), pReg->szName),
+ VERR_PDM_INVALID_DEVICE_REGISTRATION);
+ AssertMsgReturn((pReg->fFlags & PDM_DEVREG_FLAGS_HOST_BITS_MASK) == PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT,
+ ("Invalid host bits flags! fFlags=%#x (Device %s)\n", pReg->fFlags, pReg->szName),
+ VERR_PDM_INVALID_DEVICE_HOST_BITS);
+ AssertMsgReturn((pReg->fFlags & PDM_DEVREG_FLAGS_GUEST_BITS_MASK),
+ ("Invalid guest bits flags! fFlags=%#x (Device %s)\n", pReg->fFlags, pReg->szName),
+ VERR_PDM_INVALID_DEVICE_REGISTRATION);
+ AssertMsgReturn(pReg->fClass,
+ ("No class! (Device %s)\n", pReg->szName),
+ VERR_PDM_INVALID_DEVICE_REGISTRATION);
+ AssertMsgReturn(pReg->cMaxInstances > 0,
+ ("Max instances %u! (Device %s)\n", pReg->cMaxInstances, pReg->szName),
+ VERR_PDM_INVALID_DEVICE_REGISTRATION);
+ AssertMsgReturn(pReg->cbInstanceCC <= (uint32_t)(pReg->fFlags & (PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0) ? 96 * _1K : _1M),
+ ("Instance size %d bytes! (Device %s)\n", pReg->cbInstanceCC, pReg->szName),
+ VERR_PDM_INVALID_DEVICE_REGISTRATION);
+ AssertMsgReturn(pReg->pfnConstruct,
+ ("No constructor! (Device %s)\n", pReg->szName),
+ VERR_PDM_INVALID_DEVICE_REGISTRATION);
+ AssertLogRelMsgReturn((pReg->fFlags & PDM_DEVREG_FLAGS_GUEST_BITS_MASK) == PDM_DEVREG_FLAGS_GUEST_BITS_DEFAULT,
+ ("PDM: Rejected device '%s' because it didn't match the guest bits.\n", pReg->szName),
+ VERR_PDM_INVALID_DEVICE_GUEST_BITS);
+ AssertLogRelMsg(pReg->u32VersionEnd == PDM_DEVREG_VERSION,
+ ("u32VersionEnd=%#x, expected %#x. (szName=%s)\n",
+ pReg->u32VersionEnd, PDM_DEVREG_VERSION, pReg->szName));
+
+ /*
+ * Check for duplicates.
+ */
+ int rc = VINF_SUCCESS;
+ PCTSTDEVPDMDEVREGCBINT pRegCB = (PCTSTDEVPDMDEVREGCBINT)pCallbacks;
+ if (!tstDevPdmDeviceFind(pReg->szName, NULL /*ppR0Reg*/))
+ {
+ PTSTDEVPDMDEV pPdmDev = (PTSTDEVPDMDEV)RTMemAllocZ(sizeof(TSTDEVPDMDEV));
+ if (RT_LIKELY(pPdmDev))
+ {
+ pPdmDev->pPdmMod = pRegCB->pMod;
+ pRegCB->pMod->cRefs++;
+ pPdmDev->pReg = pReg;
+ RTListAppend(&g_LstPdmDevs, &pPdmDev->NdPdmDevs);
+ return VINF_SUCCESS;
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+ else
+ rc = VERR_PDM_DEVICE_NAME_CLASH;
+
+ return rc;
+}
+
+
+/**
+ * Checks whether the given PDM module filename was already loaded.
+ *
+ * @returns Pointer to already loaded plugin, NULL if not found.
+ * @param pszFilename The filename to check.
+ */
+static PCTSTDEVPDMMOD tstDevPdmModFind(const char *pszFilename)
+{
+ PCTSTDEVPDMMOD pIt;
+ RTListForEach(&g_LstPdmMods, pIt, TSTDEVPDMMOD, NdPdmMods)
+ {
+ if (!RTStrCmp(pIt->pszFilename, pszFilename))
+ return pIt;
+ }
+
+ return NULL;
+}
+
+
+/**
+ * Resolve an external symbol during RTLdrGetBits().
+ *
+ * @returns iprt status code.
+ * @param hLdrMod The loader module handle.
+ * @param pszModule Module name.
+ * @param pszSymbol Symbol name, NULL if uSymbol should be used.
+ * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.
+ * @param pValue Where to store the symbol value (address).
+ * @param pvUser User argument.
+ */
+static DECLCALLBACK(int) tstDevPdmLoadR0RcModGetImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol,
+ unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
+{
+ RT_NOREF(hLdrMod, uSymbol, pszModule);
+ PTSTDEVPDMMOD pMod = (PTSTDEVPDMMOD)pvUser;
+
+ RTPrintf("Looking for %s\n", pszSymbol);
+
+ /* Resolve the import. */
+ PCTSTDEVPDMR0IMPORTS pImpDesc = NULL;
+ bool fFound = false;
+ for (uint32_t i = 0; i < RT_ELEMENTS(g_aPdmR0Imports); i++)
+ {
+ pImpDesc = &g_aPdmR0Imports[i];
+ if (!strcmp(pszSymbol, pImpDesc->pszSymbol))
+ {
+ fFound = true;
+ break;
+ }
+ }
+
+ int rc = VERR_SYMBOL_NOT_FOUND;
+ if (fFound)
+ {
+ /* Check whether the symbol has a trampoline already. */
+ PTSTDEVPDMMODTRAMPOLINE pTrampoline = (PTSTDEVPDMMODTRAMPOLINE)pMod->R0Rc.pbTrampoline;
+ for (uint32_t i = 0; i < pMod->R0Rc.cTrampolines; i++)
+ {
+ if (pTrampoline->AddrTarget == (uintptr_t)pImpDesc->pfn)
+ break;
+ pTrampoline++;
+ }
+
+ /* Create new trampoline if not found. */
+ if (pTrampoline->AddrTarget != (uintptr_t)pImpDesc->pfn)
+ {
+ if (pMod->R0Rc.cTrampolines < pMod->R0Rc.cTrampolinesMax)
+ {
+ pTrampoline = pMod->R0Rc.pTrampolineNext;
+ pMod->R0Rc.pTrampolineNext++;
+ pMod->R0Rc.cTrampolines++;
+ pTrampoline->abJmp[0] = 0xff; /* jmp */
+ pTrampoline->abJmp[1] = 0x25; /* rip */
+ pTrampoline->abJmp[2] = 0x00; /* offset */
+ pTrampoline->abJmp[3] = 0x00;
+ pTrampoline->abJmp[4] = 0x00;
+ pTrampoline->abJmp[5] = 0x00;
+ pTrampoline->AddrTarget = (uintptr_t)pImpDesc->pfn;
+ rc = VINF_SUCCESS;
+ }
+ else
+ {
+ rc = VERR_SYMBOL_NOT_FOUND;
+ AssertFailed();
+ }
+ }
+ else
+ rc = VINF_SUCCESS;
+
+ if (RT_SUCCESS(rc))
+ *pValue = (RTUINTPTR)pTrampoline;
+ }
+ else
+ AssertFailed();
+
+ return rc;
+}
+
+
+/**
+ * The PDMR0RegisterModule() export called by loaded R0 modules.
+ *
+ * @returns VBox status code.
+ * @param hMod The module handle.
+ * @param pModReg The module registration structure.
+ */
+static int tstDevPdmR0RegisterModule(void *hMod, PPDMDEVMODREGR0 pModReg)
+{
+ RT_NOREF(hMod);
+ RTListAppend(&g_LstPdmR0Mods, &pModReg->ListEntry);
+ return VINF_SUCCESS;
+}
+
+
+
+/**
+ * Loads a new R0 modules given by the filename.
+ *
+ * @returns VBox status code.
+ * @param pMod Pointer to module structure.
+ */
+static int tstDevPdmLoadR0RcMod(PTSTDEVPDMMOD pMod)
+{
+ int rc = VINF_SUCCESS;
+ const char *pszFile = RTPathFilename(pMod->pszFilename);
+
+ /* Check whether the plugin is loaded first. */
+ if (!tstDevPdmModFind(pszFile))
+ {
+ /*
+ * R0 modules need special treatment as these are relocatable images
+ * which are supposed to run in ring 0.
+ */
+ rc = RTLdrOpen(pMod->pszFilename, 0, RTLDRARCH_HOST, &pMod->hLdrMod);
+ if (RT_SUCCESS(rc))
+ {
+ size_t cb = RTLdrSize(pMod->hLdrMod) + 1024 * sizeof(TSTDEVPDMMODTRAMPOLINE);
+
+ /* Allocate bits. */
+ uint32_t fFlags = RTMEMALLOCEX_FLAGS_EXEC;
+#ifdef RT_OS_LINUX
+ /*
+ * amd64 ELF binaries support only a 2GB code segment everything must be in
+ * (X86_64_PC32 relocation) so we have to use a trampoline to the final destination
+ * which is kept close to the imported module.
+ */
+ fFlags |= RTMEMALLOCEX_FLAGS_32BIT_REACH;
+#endif
+ rc = RTMemAllocEx(cb, 0, fFlags, (void **)&pMod->R0Rc.pbTrampoline);
+ pMod->R0Rc.cbBits = cb;
+ if (RT_SUCCESS(rc))
+ {
+ pMod->R0Rc.pvBits = pMod->R0Rc.pbTrampoline + 1024 * sizeof(TSTDEVPDMMODTRAMPOLINE);
+ pMod->R0Rc.cTrampolinesMax = 1024;
+ pMod->R0Rc.cTrampolines = 0;
+ pMod->R0Rc.pTrampolineNext = (PTSTDEVPDMMODTRAMPOLINE)pMod->R0Rc.pbTrampoline;
+ /* Get the bits. */
+ rc = RTLdrGetBits(pMod->hLdrMod, pMod->R0Rc.pvBits, (uintptr_t)pMod->R0Rc.pvBits,
+ tstDevPdmLoadR0RcModGetImport, pMod);
+ if (RT_SUCCESS(rc))
+ {
+ /* Resolve module init entry and call it. */
+ PFNR0MODULEINIT pfnR0ModuleInit;
+ rc = RTLdrGetSymbolEx(pMod->hLdrMod, pMod->R0Rc.pvBits, (uintptr_t)pMod->R0Rc.pvBits,
+ UINT32_MAX, "ModuleInit", (PRTLDRADDR)&pfnR0ModuleInit);
+ if (RT_SUCCESS(rc))
+ rc = pfnR0ModuleInit(pMod);
+ }
+ else
+ RTMemFreeEx(pMod->R0Rc.pbTrampoline, pMod->R0Rc.cbBits);
+ }
+
+ if (RT_FAILURE(rc))
+ RTLdrClose(pMod->hLdrMod);
+ }
+ }
+
+ return rc;
+}
+
+
+/**
+ * Loads the given
+ */
+static int tstDevPdmLoadR3Mod(PTSTDEVPDMMOD pMod)
+{
+ int rc = RTLdrLoad(pMod->pszFilename, &pMod->hLdrMod);
+ if (RT_SUCCESS(rc))
+ {
+ FNPDMVBOXDEVICESREGISTER *pfnVBoxDevicesRegister;
+ rc = RTLdrGetSymbol(pMod->hLdrMod, "VBoxDevicesRegister", (void**)&pfnVBoxDevicesRegister);
+ if (RT_FAILURE(rc) || !pfnVBoxDevicesRegister)
+ {
+ LogFunc(("error resolving the entry point %s in plugin %s, rc=%Rrc, pfnPluginLoad=%#p\n",
+ "VBoxDevicesRegister", pMod->pszFilename, rc, pfnVBoxDevicesRegister));
+ if (RT_SUCCESS(rc))
+ rc = VERR_SYMBOL_NOT_FOUND;
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ TSTDEVPDMDEVREGCBINT RegCB;
+ RegCB.Core.u32Version = PDM_DEVREG_CB_VERSION;
+ RegCB.Core.pfnRegister = tstDevPdmR3DevReg_Register;
+ RegCB.pMod = pMod;
+ rc = pfnVBoxDevicesRegister(&RegCB.Core, VBOX_VERSION);
+ }
+ else
+ LogFunc(("ignored plugin '%s': rc=%Rrc\n", pMod->pszFilename, rc));
+
+ if (RT_FAILURE(rc))
+ RTLdrClose(pMod->hLdrMod);
+ }
+
+ return rc;
+}
+
+
+/**
+ * Tries to loads the given PDM module.
+ *
+ * @returns VBox status code.
+ * @param pszFilename The filename to load.
+ * @param enmModType The module type.
+ */
+static int tstDevPdmLoadMod(const char *pszFilename, TSTDEVPDMMODTYPE enmModType)
+{
+ int rc = VINF_SUCCESS;
+
+ /* Check whether the plugin is loaded first. */
+ if (!tstDevPdmModFind(pszFilename))
+ {
+ PTSTDEVPDMMOD pMod = (PTSTDEVPDMMOD)RTMemAllocZ(sizeof(TSTDEVPDMMOD));
+ if (RT_LIKELY(pMod))
+ {
+ pMod->pszFilename = RTStrDup(pszFilename);
+ pMod->cRefs = 1;
+ pMod->enmType = enmModType;
+
+ if (enmModType == TSTDEVPDMMODTYPE_R3)
+ rc = tstDevPdmLoadR3Mod(pMod);
+ else if (enmModType == TSTDEVPDMMODTYPE_RC || enmModType == TSTDEVPDMMODTYPE_R0)
+ rc = tstDevPdmLoadR0RcMod(pMod);
+
+ if (RT_SUCCESS(rc))
+ RTListAppend(&g_LstPdmMods, &pMod->NdPdmMods);
+ else
+ RTMemFree(pMod);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+
+ return rc;
+}
+
+
+/**
+ * Tries to resolve the given symbol from the module given.
+ *
+ * @returns VBox status code.
+ * @param pThis The device under test instance.
+ * @param pszMod The module name.
+ * @param enmModType The module type if the module needs to be loaded.
+ * @param pszSymbol The symbol to resolve.
+ * @param ppfn Where to store the value on success.
+ */
+DECLHIDDEN(int) tstDevPdmLdrGetSymbol(PTSTDEVDUTINT pThis, const char *pszMod, TSTDEVPDMMODTYPE enmModType,
+ const char *pszSymbol, PFNRT *ppfn)
+{
+ RT_NOREF(pThis);
+
+ int rc = VINF_SUCCESS;
+ PCTSTDEVPDMMOD pMod = tstDevPdmModFind(pszMod);
+ if (!pMod)
+ {
+ /* Try to load the module. */
+ rc = tstDevPdmLoadMod(pszMod, enmModType);
+ if (RT_SUCCESS(rc))
+ {
+ pMod = tstDevPdmModFind(pszMod);
+ AssertPtr(pMod);
+ }
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ if (pMod->enmType == TSTDEVPDMMODTYPE_R0 || pMod->enmType == TSTDEVPDMMODTYPE_RC)
+ rc = RTLdrGetSymbolEx(pMod->hLdrMod, pMod->R0Rc.pvBits, (uintptr_t)pMod->R0Rc.pvBits,
+ UINT32_MAX, pszSymbol, (PRTLDRADDR)ppfn);
+ else
+ rc = RTLdrGetSymbol(pMod->hLdrMod, pszSymbol, (void **)ppfn);
+ }
+
+ return rc;
+}
+
+
+/**
+ * Create a new PDM device with default config.
+ *
+ * @returns VBox status code.
+ * @param pszName Name of the device to create.
+ * @param pDut The device under test structure the created PDM device instance is exercised under.
+ */
+static int tstDevPdmDevR3Create(const char *pszName, PTSTDEVDUTINT pDut)
+{
+ int rc = VINF_SUCCESS;
+ PCTSTDEVPDMDEV pPdmDev = tstDevPdmDeviceFind(pszName, NULL);
+ if (RT_LIKELY(pPdmDev))
+ {
+ PPDMCRITSECT pCritSect;
+ /* Figure out how much we need. */
+ uint32_t cb = RT_UOFFSETOF_DYN(PDMDEVINS, achInstanceData[pPdmDev->pReg->cbInstanceCC]);
+ cb = RT_ALIGN_32(cb, 64);
+ uint32_t const offShared = cb;
+ cb += RT_ALIGN_32(pPdmDev->pReg->cbInstanceShared, 64);
+ uint32_t const cbCritSect = RT_ALIGN_32(sizeof(*pCritSect), 64);
+ cb += cbCritSect;
+ uint32_t const cbMsixState = RT_ALIGN_32(pPdmDev->pReg->cMaxMsixVectors * 16 + (pPdmDev->pReg->cMaxMsixVectors + 7) / 8, _4K);
+ uint32_t const cbPciDev = RT_ALIGN_32(RT_UOFFSETOF_DYN(PDMPCIDEV, abMsixState[cbMsixState]), 64);
+ uint32_t const cPciDevs = RT_MIN(pPdmDev->pReg->cMaxPciDevices, 1024);
+ uint32_t const cbPciDevs = cbPciDev * cPciDevs;
+ cb += cbPciDevs;
+
+ PPDMDEVINS pDevIns = (PPDMDEVINS)RTMemAllocZ(cb);
+ pDevIns->u32Version = PDM_DEVINS_VERSION;
+ pDevIns->iInstance = 0;
+ pDevIns->pReg = pPdmDev->pReg;
+ pDevIns->pvInstanceDataR3 = &pDevIns->achInstanceData[0];
+ pDevIns->pHlpR3 = &g_tstDevPdmDevHlpR3;
+ pDevIns->pCfg = &pDut->Cfg;
+ pDevIns->Internal.s.pDut = pDut;
+ pDevIns->cbRing3 = cb;
+ pDevIns->fR0Enabled = false;
+ pDevIns->fRCEnabled = false;
+ pDevIns->pvInstanceDataR3 = (uint8_t *)pDevIns + offShared;
+ pDevIns->pvInstanceDataForR3 = &pDevIns->achInstanceData[0];
+ pCritSect = (PPDMCRITSECT)((uint8_t *)pDevIns + offShared + RT_ALIGN_32(pPdmDev->pReg->cbInstanceShared, 64));
+ pDevIns->pCritSectRoR3 = pCritSect;
+ pDevIns->cbPciDev = cbPciDev;
+ pDevIns->cPciDevs = cPciDevs;
+ for (uint32_t iPciDev = 0; iPciDev < cPciDevs; iPciDev++)
+ {
+ PPDMPCIDEV pPciDev = (PPDMPCIDEV)((uint8_t *)pDevIns->pCritSectRoR3 + cbCritSect + cbPciDev * iPciDev);
+ if (iPciDev < RT_ELEMENTS(pDevIns->apPciDevs))
+ pDevIns->apPciDevs[iPciDev] = pPciDev;
+ pPciDev->cbConfig = _4K;
+ pPciDev->cbMsixState = cbMsixState;
+ pPciDev->idxSubDev = (uint16_t)iPciDev;
+ pPciDev->u32Magic = PDMPCIDEV_MAGIC;
+ }
+
+ RTCritSectInit(&pCritSect->s.CritSect);
+ rc = pPdmDev->pReg->pfnConstruct(pDevIns, 0, pDevIns->pCfg);
+ if (RT_SUCCESS(rc))
+ pDut->pDevIns = pDevIns;
+ else
+ {
+ rc = pPdmDev->pReg->pfnDestruct(pDevIns);
+ RTMemFree(pDevIns);
+ }
+ }
+ else
+ rc = VERR_NOT_FOUND;
+
+ return rc;
+}
+
+
+DECLHIDDEN(int) tstDevPdmDeviceR3Construct(PTSTDEVDUTINT pDut)
+{
+ PPDMDEVINS pDevInsR3 = pDut->pDevIns;
+
+ pDevInsR3->pReg = pDut->pPdmDev->pReg;
+ pDevInsR3->pHlpR3 = &g_tstDevPdmDevHlpR3;
+ pDevInsR3->pCfg = &pDut->Cfg;
+ pDevInsR3->Internal.s.pDut = pDut;
+
+ return pDevInsR3->pReg->pfnConstruct(pDevInsR3, 0, &pDut->Cfg);
+}
+
+
+DECLCALLBACK(void *) tstDevTestsRun_QueryInterface(PPDMIBASE pInterface, const char *pszIID)
+{
+ RT_NOREF(pInterface, pszIID);
+#if 0
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMILEDCONNECTORS, &pThis->ILedConnectors);
+ PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIANOTIFY, &pThis->IMediaNotify);
+#endif
+ return NULL;
+}
+
+/**
+ * Run a given test config.
+ *
+ * @returns VBox status code.
+ * @param pDevTstCfg The test config to run.
+ */
+static int tstDevTestsRun(PCTSTDEVCFG pDevTstCfg)
+{
+ int rc = VINF_SUCCESS;
+
+ for (uint32_t i = 0; i < pDevTstCfg->cTests; i++)
+ {
+ PCTSTDEVTEST pTest = &pDevTstCfg->aTests[i];
+
+ TSTDEVDUTINT Dut;
+ Dut.pTest = pTest;
+ Dut.enmCtx = TSTDEVDUTCTX_R3;
+ Dut.pVm = (PVM)0x1000;
+ Dut.SupSession.pDut = &Dut;
+ Dut.Cfg.pDut = &Dut;
+ Dut.pPdmDev = tstDevPdmDeviceFind(pDevTstCfg->pszDevName, NULL /*ppPdmDevR0*/);
+
+ Dut.IBaseSts.pfnQueryInterface = tstDevTestsRun_QueryInterface;
+
+ RTListInit(&Dut.LstIoPorts);
+ RTListInit(&Dut.LstMmio);
+ RTListInit(&Dut.LstTimers);
+ RTListInit(&Dut.LstMmHeap);
+ RTListInit(&Dut.LstPdmThreads);
+ RTListInit(&Dut.LstSsmHandlers);
+ RTListInit(&Dut.SupSession.LstSupSem);
+
+ rc = RTCritSectRwInit(&Dut.CritSectLists);
+ AssertRC(rc);
+
+ rc = RTCritSectInitEx(&Dut.CritSectNop.s.CritSect, RTCRITSECT_FLAGS_NOP, NIL_RTLOCKVALCLASS, RTLOCKVAL_SUB_CLASS_NONE, "DutNop");
+ AssertRC(rc);
+
+ if (!pTest->fR0Enabled)
+ rc = tstDevPdmDevR3Create(pDevTstCfg->pszDevName, &Dut);
+ else
+ rc = tstDevPdmDevR0R3Create(pDevTstCfg->pszDevName, pTest->fRCEnabled, &Dut);
+ if (RT_SUCCESS(rc))
+ {
+ PCTSTDEVTESTCASE pTestcase = tstDevTestcaseFind(pTest->papszTestcaseIds[i]);
+ if (pTestcase)
+ rc = pTestcase->pTestcaseReg->pfnTestEntry(&Dut, pTest->papTestcaseCfg[i], pTest->pacTestcaseCfgItems[i]);
+ else
+ rc = VERR_NOT_FOUND;
+ }
+ }
+
+ return rc;
+}
+
+
+int main(int argc, char *argv[])
+{
+ /*
+ * Init the runtime and parse the arguments.
+ */
+ RTEXITCODE rcExit = RTEXITCODE_SUCCESS;
+ int rc = RTR3InitExe(argc, &argv, 0);
+ if (RT_SUCCESS(rc))
+ {
+ RTListInit(&g_LstPlugins);
+ RTListInit(&g_LstTestcases);
+ RTListInit(&g_LstPdmMods);
+ RTListInit(&g_LstPdmR0Mods);
+ RTListInit(&g_LstPdmDevs);
+
+ /* Register builtin tests. */
+ tstDevRegisterTestcase(NULL, &g_TestcaseSsmFuzz);
+ tstDevRegisterTestcase(NULL, &g_TestcaseSsmLoadDbg);
+ tstDevRegisterTestcase(NULL, &g_TestcaseIoFuzz);
+
+ PCTSTDEVCFG pDevTstCfg = NULL;
+ rc = tstDevCfgLoad(argv[1], NULL, &pDevTstCfg);
+ if (RT_SUCCESS(rc))
+ {
+ if (pDevTstCfg->pszTstDevMod)
+ rc = tstDevLoadPlugin(pDevTstCfg->pszTstDevMod);
+ if (RT_SUCCESS(rc))
+ {
+ rc = tstDevPdmLoadMod(pDevTstCfg->pszPdmR3Mod, TSTDEVPDMMODTYPE_R3);
+ if ( RT_SUCCESS(rc)
+ && pDevTstCfg->pszPdmR0Mod)
+ rc = tstDevPdmLoadMod(pDevTstCfg->pszPdmR0Mod, TSTDEVPDMMODTYPE_R0);
+ if ( RT_SUCCESS(rc)
+ && pDevTstCfg->pszPdmRCMod)
+ rc = tstDevPdmLoadMod(pDevTstCfg->pszPdmRCMod, TSTDEVPDMMODTYPE_RC);
+
+ if (RT_SUCCESS(rc))
+ rc = tstDevTestsRun(pDevTstCfg);
+ else
+ rcExit = RTEXITCODE_FAILURE;
+ }
+ else
+ rcExit = RTEXITCODE_FAILURE;
+ }
+
+ tstDevCfgDestroy(pDevTstCfg);
+ }
+ else
+ rcExit = RTEXITCODE_FAILURE;
+
+ return rcExit;
+}
+
diff --git a/src/VBox/Devices/testcase/tstDeviceBuiltin.h b/src/VBox/Devices/testcase/tstDeviceBuiltin.h
new file mode 100644
index 00000000..c6d70d2f
--- /dev/null
+++ b/src/VBox/Devices/testcase/tstDeviceBuiltin.h
@@ -0,0 +1,47 @@
+/** @file
+ * tstDevice: Builtin tests.
+ */
+
+/*
+ * Copyright (C) 2020-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef VBOX_INCLUDED_SRC_testcase_tstDeviceBuiltin_h
+#define VBOX_INCLUDED_SRC_testcase_tstDeviceBuiltin_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/param.h>
+#include <VBox/types.h>
+#include <iprt/err.h>
+
+#include "tstDevicePlugin.h"
+
+RT_C_DECLS_BEGIN
+
+extern const TSTDEVTESTCASEREG g_TestcaseSsmFuzz;
+extern const TSTDEVTESTCASEREG g_TestcaseSsmLoadDbg;
+extern const TSTDEVTESTCASEREG g_TestcaseIoFuzz;
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_SRC_testcase_tstDeviceBuiltin_h */
diff --git a/src/VBox/Devices/testcase/tstDeviceCfg.cpp b/src/VBox/Devices/testcase/tstDeviceCfg.cpp
new file mode 100644
index 00000000..cb741b02
--- /dev/null
+++ b/src/VBox/Devices/testcase/tstDeviceCfg.cpp
@@ -0,0 +1,560 @@
+/* $Id: tstDeviceCfg.cpp $ */
+/** @file
+ * tstDevice - Configuration loader.
+ */
+
+/*
+ * Copyright (C) 2020-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEFAULT /** @todo */
+#include <VBox/types.h>
+#include <iprt/errcore.h>
+#include <iprt/json.h>
+#include <iprt/mem.h>
+#include <iprt/message.h>
+#include <iprt/string.h>
+
+#include "tstDeviceCfg.h"
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+
+
+/**
+ * Wrapper around RTErrInfoSetV / RTMsgErrorV.
+ *
+ * @returns @a rc
+ * @param pErrInfo Extended error info.
+ * @param rc The return code.
+ * @param pszFormat The message format.
+ * @param ... The message format arguments.
+ */
+static int tstDevCfgErrorRc(PRTERRINFO pErrInfo, int rc, const char *pszFormat, ...)
+{
+ va_list va;
+ va_start(va, pszFormat);
+ if (pErrInfo)
+ RTErrInfoSetV(pErrInfo, rc, pszFormat, va);
+ else
+ RTMsgErrorV(pszFormat, va);
+ va_end(va);
+ return rc;
+}
+
+
+/**
+ * Destroys the given configuration item array freeing all allocated resources.
+ *
+ * @param paCfg The configuration item array to destroy.
+ * @param cCfgItems Number of items in the array.
+ */
+static void tstDevCfgItemsDestroy(PTSTDEVCFGITEM paCfg, uint32_t cCfgItems)
+{
+ RT_NOREF(paCfg, cCfgItems);
+}
+
+
+/**
+ * Loads the given string from the config, creating a duplicate.
+ *
+ * @returns VBox status code.
+ * @param hJsonTop The JSON top value handle containing the value to load.
+ * @param pszValName The value name.
+ * @param ppszValCopy Where to store the pointer to the value on success, must be freed with RTStrFree().
+ * @param fMissingOk Flag whether it is considered success if the value does not exist.
+ * @param pErrInfo Pointer to the error info to fill on error.
+ */
+static int tstDevCfgLoadString(RTJSONVAL hJsonTop, const char *pszValName, char **ppszValCopy, bool fMissingOk, PRTERRINFO pErrInfo)
+{
+ RTJSONVAL hJsonVal;
+ int rc = RTJsonValueQueryByName(hJsonTop, pszValName, &hJsonVal);
+ if (RT_SUCCESS(rc))
+ {
+ const char *pszVal = RTJsonValueGetString(hJsonVal);
+ if (RT_LIKELY(pszVal))
+ {
+ *ppszValCopy = RTStrDup(pszVal);
+ if (RT_UNLIKELY(!*ppszValCopy))
+ rc = tstDevCfgErrorRc(pErrInfo, VERR_NO_STR_MEMORY, "tstDevCfg/JSON: Out of memory allocating memory for value of \"%s\" ", pszValName);
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, VERR_JSON_VALUE_INVALID_TYPE, "tstDevCfg/JSON: \"%s\" is not a string", pszValName);
+
+ RTJsonValueRelease(hJsonVal);
+ }
+ else if ( rc == VERR_NOT_FOUND
+ && fMissingOk)
+ {
+ *ppszValCopy = NULL;
+ rc = VINF_SUCCESS;
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to query \"%s\"", pszValName);
+
+ return rc;
+}
+
+
+/**
+ * Loads a bool value using the given value name from the config.
+ *
+ * @returns VBox status code.
+ * @param hJsonTop The JSON top value handle containing the value to load.
+ * @param pszValName The value name.
+ * @param pf Where to store the value on success.
+ * @param pErrInfo Pointer to the error info to fill on error.
+ */
+static int tstDevCfgLoadBool(RTJSONVAL hJsonTop, const char *pszValName, bool *pf, PRTERRINFO pErrInfo)
+{
+ int rc = RTJsonValueQueryBooleanByName(hJsonTop, pszValName, pf);
+ if (RT_FAILURE(rc))
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to query boolean value of \"%s\"", pszValName);
+
+ return rc;
+}
+
+
+/**
+ * Determines the config item type from the given.value.
+ *
+ * @returns VBox status code.
+ * @param hJsonTop The JSON top value handle containing the value to load.
+ * @param pszValName The value name.
+ * @param penmCfgItemType Where to store the determined config item type on success.
+ * @param pErrInfo Pointer to the error info to fill on error.
+ */
+static int tstDevCfgLoadCfgItemType(RTJSONVAL hJsonTop, const char *pszValName, PTSTDEVCFGITEMTYPE penmCfgItemType, PRTERRINFO pErrInfo)
+{
+ RTJSONVAL hJsonVal;
+ int rc = RTJsonValueQueryByName(hJsonTop, pszValName, &hJsonVal);
+ if (RT_SUCCESS(rc))
+ {
+ const char *pszVal = RTJsonValueGetString(hJsonVal);
+ if (!RTStrCmp(pszVal, "Integer"))
+ *penmCfgItemType = TSTDEVCFGITEMTYPE_INTEGER;
+ else if (!RTStrCmp(pszVal, "String"))
+ *penmCfgItemType = TSTDEVCFGITEMTYPE_STRING;
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, VERR_JSON_VALUE_INVALID_TYPE, "tstDevCfg/JSON: \"%s\" is not a valid config item type", pszVal);
+
+ RTJsonValueRelease(hJsonVal);
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to query \"%s\"", pszValName);
+
+ return rc;
+}
+
+
+/**
+ * Loads the config item value from the given config based on the earlier determined type.
+ *
+ * @returns VBox status code.
+ * @param hJsonTop The JSON top value handle containing the value to load.
+ * @param pszValName The value name.
+ * @param pCfg Where to store the retrieved config value.
+ * @param enmCfgItemType The earlier determined config item type.
+ * @param pErrInfo Pointer to the error info to fill on error.
+ */
+static int tstDevCfgLoadCfgItemValue(RTJSONVAL hJsonTop, const char *pszValName, PTSTDEVCFGITEM pCfg, TSTDEVCFGITEMTYPE enmCfgItemType, PRTERRINFO pErrInfo)
+{
+ RTJSONVAL hJsonVal;
+
+ int rc = RTJsonValueQueryByName(hJsonTop, pszValName, &hJsonVal);
+ if (RT_SUCCESS(rc))
+ {
+ RTJSONVALTYPE enmJsonType = RTJsonValueGetType(hJsonVal);
+
+ if ( ( enmJsonType == RTJSONVALTYPE_INTEGER
+ && enmCfgItemType == TSTDEVCFGITEMTYPE_INTEGER)
+ || ( enmJsonType == RTJSONVALTYPE_STRING
+ && enmCfgItemType == TSTDEVCFGITEMTYPE_STRING))
+ {
+ switch (enmCfgItemType)
+ {
+ case TSTDEVCFGITEMTYPE_INTEGER:
+ {
+ rc = RTJsonValueQueryInteger(hJsonVal, &pCfg->u.i64);
+ break;
+ }
+ case TSTDEVCFGITEMTYPE_STRING:
+ {
+ const char *psz = RTJsonValueGetString(hJsonVal);
+ AssertPtr(psz);
+
+ pCfg->u.psz = RTStrDup(psz);
+ if (RT_UNLIKELY(!pCfg->u.psz))
+ rc = VERR_NO_STR_MEMORY;
+ break;
+ }
+ default:
+ AssertFailed(); /* Should never ever get here. */
+ rc = tstDevCfgErrorRc(pErrInfo, VERR_INTERNAL_ERROR, "tstDevCfg/JSON: Invalid config item type %u", enmCfgItemType);
+ }
+
+ if (RT_SUCCESS(rc))
+ pCfg->enmType = enmCfgItemType;
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to query config item value");
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: JSON value type doesn't match config item type (got %u, expected %u)", enmJsonType, enmCfgItemType);
+
+ RTJsonValueRelease(hJsonVal);
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to query \"%s\"", pszValName);
+
+ return rc;
+}
+
+
+/**
+ * Loads the test configuration from the given JSON value.
+ *
+ * @returns VBox status code.
+ * @param paCfg The configuration array to fill.
+ * @param cCfgItems Number of configuration items.
+ * @param hJsonValCfg The JSON value to gather the config items from.
+ * @param pErrInfo Pointer to error info.
+ */
+static int tstDevCfgLoadTestCfgWorker(PTSTDEVCFGITEM paCfg, uint32_t cCfgItems, RTJSONVAL hJsonValCfg, PRTERRINFO pErrInfo)
+{
+ int rc = VINF_SUCCESS;
+
+ for (uint32_t i = 0; i < cCfgItems && RT_SUCCESS(rc); i++)
+ {
+ PTSTDEVCFGITEM pCfg = &paCfg[i];
+ RTJSONVAL hJsonCfg;
+
+ rc = RTJsonValueQueryByIndex(hJsonValCfg, i, &hJsonCfg);
+ if (RT_SUCCESS(rc))
+ {
+ TSTDEVCFGITEMTYPE enmCfgItemType;
+
+ rc = tstDevCfgLoadString(hJsonCfg, "Key", (char **)&pCfg->pszKey, false /*fMissingOk*/, pErrInfo);
+ if (RT_SUCCESS(rc))
+ rc = tstDevCfgLoadCfgItemType(hJsonCfg, "Type", &enmCfgItemType, pErrInfo);
+ if (RT_SUCCESS(rc))
+ rc = tstDevCfgLoadCfgItemValue(hJsonCfg, "Value", pCfg, enmCfgItemType, pErrInfo);
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to query config item %u", i);
+ }
+
+ return rc;
+}
+
+
+/**
+ * Loads a single testcase from the given JSON config value.
+ *
+ * @returns VBox status code.
+ * @param ppszTestcaseId Where to store the testcase ID on success.
+ * @param pcTestcaseCfgItems Where to store the number of testcase config items on success.
+ * @param ppTestcaseCfg Where to store the testcase config on success.
+ * @param pErrInfo Pointer to error info.
+ */
+static int tstDevCfgLoadTestcase(RTJSONVAL hJsonTestcase, const char **ppszTestcaseId, uint32_t *pcTestcaseCfgItems, PCTSTDEVCFGITEM *ppTestcaseCfg, PRTERRINFO pErrInfo)
+{
+ char *pszTestcaseId = NULL;
+ int rc = tstDevCfgLoadString(hJsonTestcase, "Testcase", &pszTestcaseId, false /*fMissingOk*/, pErrInfo);
+ if (RT_SUCCESS(rc))
+ {
+ RTJSONVAL hJsonValCfg;
+ rc = RTJsonValueQueryByName(hJsonTestcase, "Config", &hJsonValCfg);
+ if (RT_SUCCESS(rc))
+ {
+ unsigned cCfgItems = 0;
+ rc = RTJsonValueQueryArraySize(hJsonValCfg, &cCfgItems);
+ if (RT_SUCCESS(rc))
+ {
+ if (cCfgItems > 0)
+ {
+ size_t cbCfg = sizeof(TSTDEVCFGITEM) * cCfgItems;
+ PTSTDEVCFGITEM paCfg = (PTSTDEVCFGITEM)RTMemAllocZ(cbCfg);
+ if (paCfg)
+ {
+ rc = tstDevCfgLoadTestCfgWorker(paCfg, cCfgItems, hJsonValCfg, pErrInfo);
+ if (RT_SUCCESS(rc))
+ {
+ *ppszTestcaseId = pszTestcaseId;
+ *pcTestcaseCfgItems = cCfgItems;
+ *ppTestcaseCfg = paCfg;
+ }
+ else /* Error already set, free test config structure. */
+ tstDevCfgItemsDestroy(paCfg, cCfgItems);
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to allocate %zu bytes for the test config structure", cbCfg);
+ }
+ else
+ {
+ *ppszTestcaseId = pszTestcaseId;
+ *pcTestcaseCfgItems = 0;
+ *ppTestcaseCfg = NULL;
+ }
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: \"Config\" is not an array");
+
+ RTJsonValueRelease(hJsonValCfg);
+ }
+ else
+ tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to query \"Config\" value");
+
+ if (RT_FAILURE(rc))
+ RTStrFree(pszTestcaseId);
+ }
+
+ return rc;
+}
+
+
+/**
+ * Loads the testcase descriptions from the config.
+ *
+ * @returns VBox status code.
+ * @param pDevTest Where to store the testcases config on success.
+ * @param hJsonValTest Where to load the testcases config from.
+ * @param pErrInfo Pointer to error info.
+ */
+static int tstDevCfgLoadTestcases(PTSTDEVTEST pDevTest, RTJSONVAL hJsonValTest, PRTERRINFO pErrInfo)
+{
+ RTJSONVAL hJsonValTestcases;
+ int rc = RTJsonValueQueryByName(hJsonValTest, "Testcases", &hJsonValTestcases);
+ if (RT_SUCCESS(rc))
+ {
+ unsigned cTestcases = 0;
+ rc = RTJsonValueQueryArraySize(hJsonValTestcases, &cTestcases);
+ if (RT_SUCCESS(rc))
+ {
+ pDevTest->cTestcases = cTestcases;
+ if (cTestcases > 0)
+ {
+ size_t cbArray = sizeof(void *) * 2 * cTestcases + cTestcases * sizeof(uint32_t); /* One for the testcase ID and one for the associated configuration. */
+ uint8_t *pbTmp = (uint8_t *)RTMemAllocZ(cbArray);
+ if (pbTmp)
+ {
+ pDevTest->papszTestcaseIds = (const char **)pbTmp;
+ pDevTest->pacTestcaseCfgItems = (uint32_t *)&pDevTest->papszTestcaseIds[cTestcases];
+ pDevTest->papTestcaseCfg = (PCTSTDEVCFGITEM *)&pDevTest->pacTestcaseCfgItems[cTestcases];
+
+ for (uint32_t i = 0; i < cTestcases; i++)
+ {
+ RTJSONVAL hJsonTestcase;
+
+ rc = RTJsonValueQueryByIndex(hJsonValTestcases, i, &hJsonTestcase);
+ if (RT_SUCCESS(rc))
+ {
+ rc = tstDevCfgLoadTestcase(hJsonTestcase, &pDevTest->papszTestcaseIds[i],
+ &pDevTest->pacTestcaseCfgItems[i], &pDevTest->papTestcaseCfg[i], pErrInfo);
+ RTJsonValueRelease(hJsonTestcase);
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to query testcase item %u", i);
+ }
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to allocate %zu bytes for the testcases", cbArray);
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, VERR_INVALID_PARAMETER, "tstDevCfg/JSON: \"Testcases\" doesn't contain anything");
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: \"Testcases\" is not an array");
+
+ RTJsonValueRelease(hJsonValTestcases);
+ }
+ else
+ tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to query \"Testcases\" value");
+
+ return rc;
+}
+
+
+/**
+ * Loads a test config from the given JSON object.
+ *
+ * @returns VBox status code.
+ * @param pDevTest Where to store the test config on success.
+ * @param hJsonValTest Where to load the test config from.
+ * @param pErrInfo Pointer to error info.
+ */
+static int tstDevCfgLoadTest(PTSTDEVTEST pDevTest, RTJSONVAL hJsonValTest, PRTERRINFO pErrInfo)
+{
+ int rc = tstDevCfgLoadBool(hJsonValTest, "R0Enabled", &pDevTest->fR0Enabled, pErrInfo);
+ if (RT_SUCCESS(rc))
+ rc = tstDevCfgLoadBool(hJsonValTest, "RCEnabled", &pDevTest->fRCEnabled, pErrInfo);
+
+ if (RT_SUCCESS(rc))
+ {
+ RTJSONVAL hJsonValCfg;
+ rc = RTJsonValueQueryByName(hJsonValTest, "Config", &hJsonValCfg);
+ if (RT_SUCCESS(rc))
+ {
+ unsigned cCfgItems = 0;
+ rc = RTJsonValueQueryArraySize(hJsonValCfg, &cCfgItems);
+ if (RT_SUCCESS(rc))
+ {
+ pDevTest->cCfgItems = cCfgItems;
+ if (cCfgItems > 0)
+ {
+ size_t cbCfg = sizeof(TSTDEVCFGITEM) * cCfgItems;
+ PTSTDEVCFGITEM paCfg = (PTSTDEVCFGITEM)RTMemAllocZ(cbCfg);
+ if (paCfg)
+ {
+ rc = tstDevCfgLoadTestCfgWorker(paCfg, cCfgItems, hJsonValCfg, pErrInfo);
+ if (RT_SUCCESS(rc))
+ pDevTest->paCfgItems = paCfg;
+ else /* Error already set, free test config structure. */
+ tstDevCfgItemsDestroy(paCfg, cCfgItems);
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to allocate %zu bytes for the test config structure", cbCfg);
+ }
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: \"Config\" is not an array");
+
+ RTJsonValueRelease(hJsonValCfg);
+ }
+ else
+ tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to query \"Config\" value");
+ }
+
+ /* Load the test configs. */
+ if (RT_SUCCESS(rc))
+ rc = tstDevCfgLoadTestcases(pDevTest, hJsonValTest, pErrInfo);
+
+ return rc;
+}
+
+
+/**
+ * Configuration loader worker.
+ *
+ * @returns VBox status code.
+ * @param pDevTstCfg The test config structure to fill.
+ * @param hJsonRoot Handle of the root JSON value.
+ * @param hJsonValDeviceTests Handle to the test JSON array.
+ * @param pErrInfo Pointer to the error info.
+ */
+static int tstDevCfgLoadWorker(PTSTDEVCFG pDevTstCfg, RTJSONVAL hJsonRoot, RTJSONVAL hJsonValDeviceTests, PRTERRINFO pErrInfo)
+{
+ int rc = tstDevCfgLoadString(hJsonRoot, "PdmR3Module", (char **)&pDevTstCfg->pszPdmR3Mod, false /*fMissingOk*/, pErrInfo);
+ if (RT_SUCCESS(rc))
+ rc = tstDevCfgLoadString(hJsonRoot, "PdmR0Module", (char **)&pDevTstCfg->pszPdmR0Mod, true /*fMissingOk*/, pErrInfo);
+ if (RT_SUCCESS(rc))
+ rc = tstDevCfgLoadString(hJsonRoot, "PdmRCModule", (char **)&pDevTstCfg->pszPdmRCMod, true /*fMissingOk*/, pErrInfo);
+ if (RT_SUCCESS(rc))
+ rc = tstDevCfgLoadString(hJsonRoot, "TestcaseModule", (char **)&pDevTstCfg->pszTstDevMod, true /*fMissingOk*/, pErrInfo);
+ if (RT_SUCCESS(rc))
+ rc = tstDevCfgLoadString(hJsonRoot, "Device", (char **)&pDevTstCfg->pszDevName, false /*fMissingOk*/, pErrInfo);
+
+ if (RT_SUCCESS(rc))
+ {
+ /* Load the individual test configs. */
+ for (uint32_t idx = 0; idx < pDevTstCfg->cTests && RT_SUCCESS(rc); idx++)
+ {
+ RTJSONVAL hJsonValTest;
+
+ rc = RTJsonValueQueryByIndex(hJsonValDeviceTests, idx, &hJsonValTest);
+ if (RT_SUCCESS(rc))
+ {
+ rc = tstDevCfgLoadTest(&pDevTstCfg->aTests[idx], hJsonValTest, pErrInfo);
+ RTJsonValueRelease(hJsonValTest);
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to query test %u from \"DeviceTests\"", idx);
+ }
+ }
+
+ return rc;
+}
+
+
+DECLHIDDEN(int) tstDevCfgLoad(const char *pszCfgFilename, PRTERRINFO pErrInfo, PCTSTDEVCFG *ppDevTstCfg)
+{
+ RTJSONVAL hJsonRoot;
+ int rc = RTJsonParseFromFile(&hJsonRoot, pszCfgFilename, pErrInfo);
+ if (RT_SUCCESS(rc))
+ {
+ RTJSONVAL hJsonValDeviceTests;
+
+ rc = RTJsonValueQueryByName(hJsonRoot, "DeviceTests", &hJsonValDeviceTests);
+ if (RT_SUCCESS(rc))
+ {
+ unsigned cTests = 0;
+ rc = RTJsonValueQueryArraySize(hJsonValDeviceTests, &cTests);
+ if (RT_SUCCESS(rc))
+ {
+ if (cTests > 0)
+ {
+ size_t cbTestCfg = RT_UOFFSETOF_DYN(TSTDEVCFG, aTests[cTests]);
+ PTSTDEVCFG pDevTstCfg = (PTSTDEVCFG)RTMemAllocZ(cbTestCfg);
+ if (pDevTstCfg)
+ {
+ pDevTstCfg->cTests = cTests;
+ rc = tstDevCfgLoadWorker(pDevTstCfg, hJsonRoot, hJsonValDeviceTests, pErrInfo);
+ if (RT_SUCCESS(rc))
+ *ppDevTstCfg = pDevTstCfg;
+ else /* Error already set, free test config structure. */
+ tstDevCfgDestroy(pDevTstCfg);
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to allocate %zu bytes for the test config structure", cbTestCfg);
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: \"DeviceTests\" is empty");
+ }
+ else
+ rc = tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: \"DeviceTests\" is not an array");
+
+ RTJsonValueRelease(hJsonValDeviceTests);
+ }
+ else
+ tstDevCfgErrorRc(pErrInfo, rc, "tstDevCfg/JSON: Failed to query \"DeviceTests\" value");
+
+ RTJsonValueRelease(hJsonRoot);
+ }
+
+ return rc;
+}
+
+
+DECLHIDDEN(void) tstDevCfgDestroy(PCTSTDEVCFG pDevTstCfg)
+{
+ RT_NOREF(pDevTstCfg);
+}
+
diff --git a/src/VBox/Devices/testcase/tstDeviceCfg.h b/src/VBox/Devices/testcase/tstDeviceCfg.h
new file mode 100644
index 00000000..c514f987
--- /dev/null
+++ b/src/VBox/Devices/testcase/tstDeviceCfg.h
@@ -0,0 +1,169 @@
+/** @file
+ * tstDevice: Configuration handling.
+ */
+
+/*
+ * Copyright (C) 2020-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef VBOX_INCLUDED_SRC_testcase_tstDeviceCfg_h
+#define VBOX_INCLUDED_SRC_testcase_tstDeviceCfg_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/param.h>
+#include <VBox/types.h>
+#include <iprt/err.h>
+
+RT_C_DECLS_BEGIN
+
+/**
+ * Config item type.
+ */
+typedef enum TSTDEVCFGITEMTYPE
+{
+ /** Invalid type. */
+ TSTDEVCFGITEMTYPE_INVALID = 0,
+ /** String type. */
+ TSTDEVCFGITEMTYPE_STRING,
+ /** Integer value encoded in the string. */
+ TSTDEVCFGITEMTYPE_INTEGER,
+ /** Raw bytes. */
+ TSTDEVCFGITEMTYPE_BYTES,
+ /** 32bit hack. */
+ TSTDEVCFGITEMTYPE_32BIT_HACK = 0x7fffffff
+} TSTDEVCFGITEMTYPE;
+/** Pointer to a config item type. */
+typedef TSTDEVCFGITEMTYPE *PTSTDEVCFGITEMTYPE;
+
+
+/**
+ * Testcase config item.
+ */
+typedef struct TSTDEVCFGITEM
+{
+ /** The key of the item. */
+ const char *pszKey;
+ /** Type of the config item. */
+ TSTDEVCFGITEMTYPE enmType;
+ /** Type dependent data. */
+ union
+ {
+ /** String value. */
+ const char *psz;
+ /** Integer value. */
+ int64_t i64;
+ /** Raw bytes. */
+ struct
+ {
+ /** Size of the byte buffer. */
+ size_t cb;
+ /** Pointer to the raw buffer. */
+ const void *pv;
+ } RawBytes;
+ } u;
+} TSTDEVCFGITEM;
+/** Pointer to a testcase config item. */
+typedef TSTDEVCFGITEM *PTSTDEVCFGITEM;
+/** Pointer to a constant testcase config item. */
+typedef const TSTDEVCFGITEM *PCTSTDEVCFGITEM;
+
+
+/**
+ * A single test.
+ */
+typedef struct TSTDEVTEST
+{
+ /** Flag whether to enable the R0 part for testing. */
+ bool fR0Enabled;
+ /** Flag whether to enable the RC part for testing. */
+ bool fRCEnabled;
+ /** Number of configuration items for the device. */
+ uint32_t cCfgItems;
+ /** Pointer to array of configuration items for the device. */
+ PCTSTDEVCFGITEM paCfgItems;
+ /** Number of testcases to run with that device instance. */
+ uint32_t cTestcases;
+ /** Pointer to the array of testcase IDs. */
+ const char **papszTestcaseIds;
+ /** Pointer to the array of testcase configuration item numbers. */
+ uint32_t *pacTestcaseCfgItems;
+ /** Pointer to the array of configuration item array pointers for each testcase. */
+ PCTSTDEVCFGITEM *papTestcaseCfg;
+} TSTDEVTEST;
+/** Pointer to a single test. */
+typedef TSTDEVTEST *PTSTDEVTEST;
+/** Pointer to a const single test. */
+typedef const TSTDEVTEST *PCTSTDEVTEST;
+
+
+/**
+ * A device test configuration.
+ */
+typedef struct TSTDEVCFG
+{
+ /** The identifier of the device to test. */
+ const char *pszDevName;
+
+ /** R3 PDM module to load containing the device to test. */
+ const char *pszPdmR3Mod;
+ /** R0 PDM module to load containing the device to test. */
+ const char *pszPdmR0Mod;
+ /** RC PDM module to load containing the device to test. */
+ const char *pszPdmRCMod;
+
+ /** Testcase module to load. */
+ const char *pszTstDevMod;
+
+ /** Number of tests configured in the config. */
+ uint32_t cTests;
+ /** The array of tests to execute for the given device - variable in size. */
+ TSTDEVTEST aTests[1];
+} TSTDEVCFG;
+/** Pointer to a device test configuration. */
+typedef TSTDEVCFG *PTSTDEVCFG;
+/** Pointer to a const device test configuration. */
+typedef const TSTDEVCFG *PCTSTDEVCFG;
+/** Pointer to a device test configuration pointer. */
+typedef TSTDEVCFG *PPTSTDEVCFG;
+
+
+/**
+ * Loads the config from the given file returning the configuration structure on success.
+ *
+ * @returns VBox status code.
+ * @param pszCfgFilename The configuration file path to load.
+ * @param pErrInfo Where to store additional error information if loading the config fails, optional.
+ * @param ppDevTstCfg Where to store the pointer to the created test configuration on success.
+ */
+DECLHIDDEN(int) tstDevCfgLoad(const char *pszCfgFilename, PRTERRINFO pErrInfo, PCTSTDEVCFG *ppDevTstCfg);
+
+/**
+ * Destroys the given test configuration freeing all allocated resources.
+ *
+ * @param pDevTstCfg The test configuration to destroy.
+ */
+DECLHIDDEN(void) tstDevCfgDestroy(PCTSTDEVCFG pDevTstCfg);
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_SRC_testcase_tstDeviceCfg_h */
diff --git a/src/VBox/Devices/testcase/tstDeviceInternal.h b/src/VBox/Devices/testcase/tstDeviceInternal.h
new file mode 100644
index 00000000..477eb533
--- /dev/null
+++ b/src/VBox/Devices/testcase/tstDeviceInternal.h
@@ -0,0 +1,578 @@
+/** @file
+ * tstDevice: Shared definitions between the framework and the shim library.
+ */
+
+/*
+ * Copyright (C) 2017-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef VBOX_INCLUDED_SRC_testcase_tstDeviceInternal_h
+#define VBOX_INCLUDED_SRC_testcase_tstDeviceInternal_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/param.h>
+#include <VBox/types.h>
+#include <iprt/assert.h>
+#include <iprt/list.h>
+#include <iprt/semaphore.h>
+#include <iprt/critsect.h>
+
+#include "tstDeviceCfg.h"
+#include "tstDevicePlugin.h"
+
+RT_C_DECLS_BEGIN
+
+#define PDM_MAX_DEVICE_INSTANCE_SIZE _4M
+
+/** Converts PDM device instance to the device under test structure. */
+#define TSTDEV_PDMDEVINS_2_DUT(a_pDevIns) ((a_pDevIns)->Internal.s.pDut)
+
+/** Forward declaration of internal test device instance data. */
+typedef struct TSTDEVDUTINT *PTSTDEVDUTINT;
+
+
+/** Pointer to a const PDM module descriptor. */
+typedef const struct TSTDEVPDMMOD *PCTSTDEVPDMMOD;
+
+
+/**
+ * PDM device descriptor.
+ */
+typedef struct TSTDEVPDMDEV
+{
+ /** Node for the known device list. */
+ RTLISTNODE NdPdmDevs;
+ /** Pointer to the PDM module containing the device. */
+ PCTSTDEVPDMMOD pPdmMod;
+ /** Device registration structure. */
+ const struct PDMDEVREGR3 *pReg;
+} TSTDEVPDMDEV;
+/** Pointer to a PDM device descriptor .*/
+typedef TSTDEVPDMDEV *PTSTDEVPDMDEV;
+/** Pointer to a constant PDM device descriptor .*/
+typedef const TSTDEVPDMDEV *PCTSTDEVPDMDEV;
+
+
+/**
+ * CFGM node structure.
+ */
+typedef struct CFGMNODE
+{
+ /** Device under test this CFGM node is for. */
+ PTSTDEVDUTINT pDut;
+ /** @todo: */
+} CFGMNODE;
+
+
+/**
+ * Private device instance data.
+ */
+typedef struct PDMDEVINSINTR3
+{
+ /** Pointer to the device under test the PDM device instance is for. */
+ PTSTDEVDUTINT pDut;
+} PDMDEVINSINTR3;
+AssertCompile(sizeof(PDMDEVINSINTR3) <= (HC_ARCH_BITS == 32 ? 72 : 112 + 0x28));
+
+/**
+ * Private device instance data.
+ */
+typedef struct PDMDEVINSINTR0
+{
+ /** Pointer to the device under test the PDM device instance is for. */
+ PTSTDEVDUTINT pDut;
+} PDMDEVINSINTR0;
+AssertCompile(sizeof(PDMDEVINSINTR0) <= (HC_ARCH_BITS == 32 ? 72 : 112 + 0x28));
+
+/**
+ * Private device instance data.
+ */
+typedef struct PDMDEVINSINTRC
+{
+ /** Pointer to the device under test the PDM device instance is for. */
+ PTSTDEVDUTINT pDut;
+} PDMDEVINSINTRC;
+AssertCompile(sizeof(PDMDEVINSINTRC) <= (HC_ARCH_BITS == 32 ? 72 : 112 + 0x28));
+
+typedef struct PDMPCIDEVINT
+{
+ bool fRegistered;
+} PDMPCIDEVINT;
+
+
+/**
+ * Internal PDM critical section structure.
+ */
+typedef struct PDMCRITSECTINT
+{
+ /** The actual critical section used for emulation. */
+ RTCRITSECT CritSect;
+} PDMCRITSECTINT;
+AssertCompile(sizeof(PDMCRITSECTINT) <= (HC_ARCH_BITS == 32 ? 0x80 : 0xc0));
+
+
+/**
+ * SSM handle state.
+ */
+typedef struct SSMHANDLE
+{
+ /** Pointer to the device under test the handle is for. */
+ PTSTDEVDUTINT pDut;
+ /** The saved state data buffer. */
+ uint8_t *pbSavedState;
+ /** Size of the saved state. */
+ size_t cbSavedState;
+ /** Current offset into the data buffer. */
+ uint32_t offDataBuffer;
+ /** Current unit version. */
+ uint32_t uCurUnitVer;
+ /** Status code. */
+ int rc;
+} SSMHANDLE;
+
+
+/**
+ * MM Heap allocation.
+ */
+typedef struct TSTDEVMMHEAPALLOC
+{
+ /** Node for the list of allocations. */
+ RTLISTNODE NdMmHeap;
+ /** Pointer to the device under test the allocation was made for. */
+ PTSTDEVDUTINT pDut;
+ /** Size of the allocation. */
+ size_t cbAlloc;
+ /** Start of the real allocation. */
+ RT_FLEXIBLE_ARRAY_EXTENSION
+ uint8_t abAlloc[RT_FLEXIBLE_ARRAY];
+} TSTDEVMMHEAPALLOC;
+/** Pointer to a MM Heap allocation. */
+typedef TSTDEVMMHEAPALLOC *PTSTDEVMMHEAPALLOC;
+/** Pointer to a const MM Heap allocation. */
+typedef const TSTDEVMMHEAPALLOC *PCTSTDEVMMHEAPALLOC;
+
+AssertCompileMemberAlignment(TSTDEVMMHEAPALLOC, abAlloc, HC_ARCH_BITS == 64 ? 16 : 8);
+
+
+/**
+ * The usual device/driver/internal/external stuff.
+ */
+typedef enum
+{
+ /** The usual invalid entry. */
+ PDMTHREADTYPE_INVALID = 0,
+ /** Device type. */
+ PDMTHREADTYPE_DEVICE,
+ /** USB Device type. */
+ PDMTHREADTYPE_USB,
+ /** Driver type. */
+ PDMTHREADTYPE_DRIVER,
+ /** Internal type. */
+ PDMTHREADTYPE_INTERNAL,
+ /** External type. */
+ PDMTHREADTYPE_EXTERNAL,
+ /** The usual 32-bit hack. */
+ PDMTHREADTYPE_32BIT_HACK = 0x7fffffff
+} PDMTHREADTYPE;
+
+
+/**
+ * The internal structure for the thread.
+ */
+typedef struct PDMTHREADINT
+{
+ /** Node for the list of threads. */
+ RTLISTNODE NdPdmThrds;
+ /** Pointer to the device under test the allocation was made for. */
+ PTSTDEVDUTINT pDut;
+ /** The event semaphore the thread blocks on when not running. */
+ RTSEMEVENTMULTI BlockEvent;
+ /** The event semaphore the thread sleeps on while running. */
+ RTSEMEVENTMULTI SleepEvent;
+ /** The thread type. */
+ PDMTHREADTYPE enmType;
+} PDMTHREADINT;
+
+
+#define PDMTHREADINT_DECLARED
+#define PDMCRITSECTINT_DECLARED
+#define PDMDEVINSINT_DECLARED
+#define PDMPCIDEVINT_DECLARED
+#define VMM_INCLUDED_SRC_include_VMInternal_h
+#define VMM_INCLUDED_SRC_include_VMMInternal_h
+RT_C_DECLS_END
+#include <VBox/vmm/pdmcritsect.h>
+#include <VBox/vmm/pdmthread.h>
+#include <VBox/vmm/pdmdev.h>
+#include <VBox/vmm/pdmpci.h>
+#include <VBox/vmm/pdmdrv.h>
+#include <VBox/vmm/tm.h>
+RT_C_DECLS_BEGIN
+
+
+/**
+ * TM timer structure.
+ */
+typedef struct TMTIMER
+{
+ /** List of timers created by the device. */
+ RTLISTNODE NdDevTimers;
+ /** Clock this timer belongs to. */
+ TMCLOCK enmClock;
+ /** Callback to call when the timer expires. */
+ PFNTMTIMERDEV pfnCallbackDev;
+ /** Opaque user data to pass to the callback. */
+ void *pvUser;
+ /** Flags. */
+ uint32_t fFlags;
+ /** Assigned critical section. */
+ PPDMCRITSECT pCritSect;
+ /** @todo: */
+} TMTIMER;
+
+
+/**
+ * PDM module descriptor type.
+ */
+typedef enum TSTDEVPDMMODTYPE
+{
+ /** Invalid module type. */
+ TSTDEVPDMMODTYPE_INVALID = 0,
+ /** Ring 3 module. */
+ TSTDEVPDMMODTYPE_R3,
+ /** Ring 0 module. */
+ TSTDEVPDMMODTYPE_R0,
+ /** Raw context module. */
+ TSTDEVPDMMODTYPE_RC,
+ /** 32bit hack. */
+ TSTDEVPDMMODTYPE_32BIT_HACK = 0x7fffffff
+} TSTDEVPDMMODTYPE;
+
+/**
+ * Registered I/O port access handler.
+ */
+typedef struct RTDEVDUTIOPORT
+{
+ /** Node for the list of registered handlers. */
+ RTLISTNODE NdIoPorts;
+ /** Start I/O port the handler is for. */
+ RTIOPORT PortStart;
+ /** Number of ports handled. */
+ RTIOPORT cPorts;
+ /** Opaque user data - R3. */
+ void *pvUserR3;
+ /** Out handler - R3. */
+ PFNIOMIOPORTNEWOUT pfnOutR3;
+ /** In handler - R3. */
+ PFNIOMIOPORTNEWIN pfnInR3;
+ /** Out string handler - R3. */
+ PFNIOMIOPORTNEWOUTSTRING pfnOutStrR3;
+ /** In string handler - R3. */
+ PFNIOMIOPORTNEWINSTRING pfnInStrR3;
+
+ /** Opaque user data - R0. */
+ void *pvUserR0;
+ /** Out handler - R0. */
+ PFNIOMIOPORTNEWOUT pfnOutR0;
+ /** In handler - R0. */
+ PFNIOMIOPORTNEWIN pfnInR0;
+ /** Out string handler - R0. */
+ PFNIOMIOPORTNEWOUTSTRING pfnOutStrR0;
+ /** In string handler - R0. */
+ PFNIOMIOPORTNEWINSTRING pfnInStrR0;
+
+#ifdef TSTDEV_SUPPORTS_RC
+ /** Opaque user data - RC. */
+ void *pvUserRC;
+ /** Out handler - RC. */
+ PFNIOMIOPORTNEWOUT pfnOutRC;
+ /** In handler - RC. */
+ PFNIOMIOPORTNEWIN pfnInRC;
+ /** Out string handler - RC. */
+ PFNIOMIOPORTNEWOUTSTRING pfnOutStrRC;
+ /** In string handler - RC. */
+ PFNIOMIOPORTNEWINSTRING pfnInStrRC;
+#endif
+} RTDEVDUTIOPORT;
+/** Pointer to a registered I/O port handler. */
+typedef RTDEVDUTIOPORT *PRTDEVDUTIOPORT;
+/** Pointer to a const I/O port handler. */
+typedef const RTDEVDUTIOPORT *PCRTDEVDUTIOPORT;
+
+
+/**
+ * Registered MMIO port access handler.
+ */
+typedef struct RTDEVDUTMMIO
+{
+ /** Node for the list of registered handlers. */
+ RTLISTNODE NdMmio;
+ /** Start address of the MMIO region when mapped. */
+ RTGCPHYS GCPhysStart;
+ /** Size of the MMIO region in bytes. */
+ RTGCPHYS cbRegion;
+ /** Opaque user data - R3. */
+ void *pvUserR3;
+ /** Write handler - R3. */
+ PFNIOMMMIONEWWRITE pfnWriteR3;
+ /** Read handler - R3. */
+ PFNIOMMMIONEWREAD pfnReadR3;
+ /** Fill handler - R3. */
+ PFNIOMMMIONEWFILL pfnFillR3;
+
+ /** Opaque user data - R0. */
+ void *pvUserR0;
+ /** Write handler - R0. */
+ PFNIOMMMIONEWWRITE pfnWriteR0;
+ /** Read handler - R0. */
+ PFNIOMMMIONEWREAD pfnReadR0;
+ /** Fill handler - R0. */
+ PFNIOMMMIONEWFILL pfnFillR0;
+
+#ifdef TSTDEV_SUPPORTS_RC
+ /** Opaque user data - RC. */
+ void *pvUserRC;
+ /** Write handler - RC. */
+ PFNIOMMMIONEWWRITE pfnWriteRC;
+ /** Read handler - RC. */
+ PFNIOMMMIONEWREAD pfnReadRC;
+ /** Fill handler - RC. */
+ PFNIOMMMIONEWFILL pfnFillRC;
+#endif
+} RTDEVDUTMMIO;
+/** Pointer to a registered MMIO handler. */
+typedef RTDEVDUTMMIO *PRTDEVDUTMMIO;
+/** Pointer to a const MMIO handler. */
+typedef const RTDEVDUTMMIO *PCRTDEVDUTMMIO;
+
+
+#ifdef IN_RING3
+/**
+ * Registered SSM handlers.
+ */
+typedef struct TSTDEVDUTSSM
+{
+ /** Node for the list of registered SSM handlers. */
+ RTLISTNODE NdSsm;
+ /** Version */
+ uint32_t uVersion;
+ PFNSSMDEVLIVEPREP pfnLivePrep;
+ PFNSSMDEVLIVEEXEC pfnLiveExec;
+ PFNSSMDEVLIVEVOTE pfnLiveVote;
+ PFNSSMDEVSAVEPREP pfnSavePrep;
+ PFNSSMDEVSAVEEXEC pfnSaveExec;
+ PFNSSMDEVSAVEDONE pfnSaveDone;
+ PFNSSMDEVLOADPREP pfnLoadPrep;
+ PFNSSMDEVLOADEXEC pfnLoadExec;
+ PFNSSMDEVLOADDONE pfnLoadDone;
+} TSTDEVDUTSSM;
+/** Pointer to the registered SSM handlers. */
+typedef TSTDEVDUTSSM *PTSTDEVDUTSSM;
+/** Pointer to a const SSM handler. */
+typedef const TSTDEVDUTSSM *PCTSTDEVDUTSSM;
+#endif
+
+
+/**
+ * The Support Driver session state.
+ */
+typedef struct TSTDEVSUPDRVSESSION
+{
+ /** Pointer to the owning device under test instance. */
+ PTSTDEVDUTINT pDut;
+ /** List of event semaphores. */
+ RTLISTANCHOR LstSupSem;
+} TSTDEVSUPDRVSESSION;
+/** Pointer to the Support Driver session state. */
+typedef TSTDEVSUPDRVSESSION *PTSTDEVSUPDRVSESSION;
+
+/** Converts a Support Driver session handle to the internal state. */
+#define TSTDEV_PSUPDRVSESSION_2_PTSTDEVSUPDRVSESSION(a_pSession) ((PTSTDEVSUPDRVSESSION)(a_pSession))
+/** Converts the internal session state to a Support Driver session handle. */
+#define TSTDEV_PTSTDEVSUPDRVSESSION_2_PSUPDRVSESSION(a_pSession) ((PSUPDRVSESSION)(a_pSession))
+
+/**
+ * Support driver event semaphore.
+ */
+typedef struct TSTDEVSUPSEMEVENT
+{
+ /** Node for the event semaphore list. */
+ RTLISTNODE NdSupSem;
+ /** Flag whether this is multi event semaphore. */
+ bool fMulti;
+ /** Event smeaphore handles depending on the flag above. */
+ union
+ {
+ RTSEMEVENT hSemEvt;
+ RTSEMEVENTMULTI hSemEvtMulti;
+ } u;
+} TSTDEVSUPSEMEVENT;
+/** Pointer to a support event semaphore state. */
+typedef TSTDEVSUPSEMEVENT *PTSTDEVSUPSEMEVENT;
+
+/** Converts a Support event semaphore handle to the internal state. */
+#define TSTDEV_SUPSEMEVENT_2_PTSTDEVSUPSEMEVENT(a_pSupSemEvt) ((PTSTDEVSUPSEMEVENT)(a_pSupSemEvt))
+/** Converts the internal session state to a Support event semaphore handle. */
+#define TSTDEV_PTSTDEVSUPSEMEVENT_2_SUPSEMEVENT(a_pSupSemEvt) ((SUPSEMEVENT)(a_pSupSemEvt))
+
+/**
+ * The contex the device under test is currently in.
+ */
+typedef enum TSTDEVDUTCTX
+{
+ /** Invalid context. */
+ TSTDEVDUTCTX_INVALID = 0,
+ /** R3 context. */
+ TSTDEVDUTCTX_R3,
+ /** R0 context. */
+ TSTDEVDUTCTX_R0,
+ /** RC context. */
+ TSTDEVDUTCTX_RC,
+ /** 32bit hack. */
+ TSTDEVDUTCTX_32BIT_HACK = 0x7fffffff
+} TSTDEVDUTCTX;
+
+/**
+ * PCI region descriptor.
+ */
+typedef struct TSTDEVDUTPCIREGION
+{
+ /** Size of the region. */
+ RTGCPHYS cbRegion;
+ /** Address space type. */
+ PCIADDRESSSPACE enmType;
+ /** Region mapping callback. */
+ PFNPCIIOREGIONMAP pfnRegionMap;
+} TSTDEVDUTPCIREGION;
+/** Pointer to a PCI region descriptor. */
+typedef TSTDEVDUTPCIREGION *PTSTDEVDUTPCIREGION;
+/** Pointer to a const PCI region descriptor. */
+typedef const TSTDEVDUTPCIREGION *PCTSTDEVDUTPCIREGION;
+
+/**
+ * Device under test instance data.
+ */
+typedef struct TSTDEVDUTINT
+{
+ /** Pointer to the test this device is running under. */
+ PCTSTDEVTEST pTest;
+ /** The PDM device registration record. */
+ PCTSTDEVPDMDEV pPdmDev;
+ /** Pointer to the PDM device instance. */
+ struct PDMDEVINSR3 *pDevIns;
+ /** Pointer to the PDM R0 device instance. */
+ struct PDMDEVINSR0 *pDevInsR0;
+ /** CFGM root config node for the device. */
+ CFGMNODE Cfg;
+ /** Current device context. */
+ TSTDEVDUTCTX enmCtx;
+ /** Critical section protecting the lists below. */
+ RTCRITSECTRW CritSectLists;
+ /** List of registered I/O port handlers. */
+ RTLISTANCHOR LstIoPorts;
+ /** List of timers registered. */
+ RTLISTANCHOR LstTimers;
+ /** List of registered MMIO regions. */
+ RTLISTANCHOR LstMmio;
+ /** List of MM Heap allocations. */
+ RTLISTANCHOR LstMmHeap;
+ /** List of PDM threads. */
+ RTLISTANCHOR LstPdmThreads;
+ /** List of SSM handlers (just one normally). */
+ RTLISTANCHOR LstSsmHandlers;
+ /** The SUP session we emulate. */
+ TSTDEVSUPDRVSESSION SupSession;
+ /** The NOP critical section. */
+ PDMCRITSECT CritSectNop;
+ /** The VM state associated with this device. */
+ PVM pVm;
+ /** The registered PCI device instance if this is a PCI device. */
+ PPDMPCIDEV pPciDev;
+ /** PCI Region descriptors. */
+ TSTDEVDUTPCIREGION aPciRegions[VBOX_PCI_NUM_REGIONS];
+ /** The status port interface we implement. */
+ PDMIBASE IBaseSts;
+ /** */
+} TSTDEVDUTINT;
+
+
+#ifdef IN_RING3
+extern const PDMDEVHLPR3 g_tstDevPdmDevHlpR3;
+#endif
+extern const PDMDEVHLPR0 g_tstDevPdmDevHlpR0;
+
+DECLHIDDEN(int) tstDevPdmLdrGetSymbol(PTSTDEVDUTINT pThis, const char *pszMod, TSTDEVPDMMODTYPE enmModType,
+ const char *pszSymbol, PFNRT *ppfn);
+
+
+DECLINLINE(int) tstDevDutLockShared(PTSTDEVDUTINT pThis)
+{
+ return RTCritSectRwEnterShared(&pThis->CritSectLists);
+}
+
+DECLINLINE(int) tstDevDutUnlockShared(PTSTDEVDUTINT pThis)
+{
+ return RTCritSectRwLeaveShared(&pThis->CritSectLists);
+}
+
+DECLINLINE(int) tstDevDutLockExcl(PTSTDEVDUTINT pThis)
+{
+ return RTCritSectRwEnterExcl(&pThis->CritSectLists);
+}
+
+DECLINLINE(int) tstDevDutUnlockExcl(PTSTDEVDUTINT pThis)
+{
+ return RTCritSectRwLeaveExcl(&pThis->CritSectLists);
+}
+
+DECLHIDDEN(int) tstDevPdmR3ThreadCreateDevice(PTSTDEVDUTINT pDut, PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
+ PFNPDMTHREADWAKEUPDEV pfnWakeUp, size_t cbStack, RTTHREADTYPE enmType, const char *pszName);
+DECLHIDDEN(int) tstDevPdmR3ThreadCreateUsb(PTSTDEVDUTINT pDut, PPDMUSBINS pUsbIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADUSB pfnThread,
+ PFNPDMTHREADWAKEUPUSB pfnWakeUp, size_t cbStack, RTTHREADTYPE enmType, const char *pszName);
+DECLHIDDEN(int) tstDevPdmR3ThreadCreateDriver(PTSTDEVDUTINT pDut, PPDMDRVINS pDrvIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDRV pfnThread,
+ PFNPDMTHREADWAKEUPDRV pfnWakeUp, size_t cbStack, RTTHREADTYPE enmType, const char *pszName);
+DECLHIDDEN(int) tstDevPdmR3ThreadCreate(PTSTDEVDUTINT pDut, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADINT pfnThread,
+ PFNPDMTHREADWAKEUPINT pfnWakeUp, size_t cbStack, RTTHREADTYPE enmType, const char *pszName);
+DECLHIDDEN(int) tstDevPdmR3ThreadCreateExternal(PTSTDEVDUTINT pDut, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADEXT pfnThread,
+ PFNPDMTHREADWAKEUPEXT pfnWakeUp, size_t cbStack, RTTHREADTYPE enmType, const char *pszName);
+DECLHIDDEN(int) tstDevPdmR3ThreadDestroy(PPDMTHREAD pThread, int *pRcThread);
+DECLHIDDEN(int) tstDevPdmR3ThreadDestroyDevice(PTSTDEVDUTINT pDut, PPDMDEVINS pDevIns);
+DECLHIDDEN(int) tstDevPdmR3ThreadDestroyUsb(PTSTDEVDUTINT pDut, PPDMUSBINS pUsbIns);
+DECLHIDDEN(int) tstDevPdmR3ThreadDestroyDriver(PTSTDEVDUTINT pDut, PPDMDRVINS pDrvIns);
+DECLHIDDEN(void) tstDevPdmR3ThreadDestroyAll(PTSTDEVDUTINT pDut);
+DECLHIDDEN(int) tstDevPdmR3ThreadIAmSuspending(PPDMTHREAD pThread);
+DECLHIDDEN(int) tstDevPdmR3ThreadIAmRunning(PPDMTHREAD pThread);
+DECLHIDDEN(int) tstDevPdmR3ThreadSleep(PPDMTHREAD pThread, RTMSINTERVAL cMillies);
+DECLHIDDEN(int) tstDevPdmR3ThreadSuspend(PPDMTHREAD pThread);
+DECLHIDDEN(int) tstDevPdmR3ThreadResume(PPDMTHREAD pThread);
+
+
+DECLHIDDEN(PCTSTDEVPDMDEV) tstDevPdmDeviceFind(const char *pszName, PCPDMDEVREGR0 *ppR0Reg);
+DECLHIDDEN(int) tstDevPdmDeviceR3Construct(PTSTDEVDUTINT pDut);
+
+DECLHIDDEN(int) tstDevPdmDevR0R3Create(const char *pszName, bool fRCEnabled, PTSTDEVDUTINT pDut);
+
+
+RT_C_DECLS_END
+
+#endif /* !VBOX_INCLUDED_SRC_testcase_tstDeviceInternal_h */
diff --git a/src/VBox/Devices/testcase/tstDeviceIoFuzz.cpp b/src/VBox/Devices/testcase/tstDeviceIoFuzz.cpp
new file mode 100644
index 00000000..0eade5a6
--- /dev/null
+++ b/src/VBox/Devices/testcase/tstDeviceIoFuzz.cpp
@@ -0,0 +1,269 @@
+/* $Id: tstDeviceIoFuzz.cpp $ */
+/** @file
+ * tstDeviceSsmFuzz - I/O fuzzing testcase.
+ */
+
+/*
+ * Copyright (C) 2021-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEFAULT /** @todo */
+#include <VBox/types.h>
+#include <iprt/errcore.h>
+#include <iprt/mem.h>
+#include <iprt/fuzz.h>
+#include <iprt/time.h>
+#include <iprt/rand.h>
+#include <iprt/string.h>
+#include <iprt/stream.h>
+
+#include "tstDeviceBuiltin.h"
+#include "tstDeviceCfg.h"
+#include "tstDeviceInternal.h"
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+
+
+static const uint32_t g_aAccWidths[] = { 1, 2, 4, 8 };
+
+static PCTSTDEVCFGITEM tstDevSsmFuzzGetCfgItem(PCTSTDEVCFGITEM paCfg, uint32_t cCfgItems, const char *pszName)
+{
+ for (uint32_t i = 0; i < cCfgItems; i++)
+ {
+ if (!RTStrCmp(paCfg[i].pszKey, pszName))
+ return &paCfg[i];
+ }
+
+ return NULL;
+}
+
+
+static uint64_t tstDevSsmFuzzGetCfgU64(PCTSTDEVCFGITEM paCfg, uint32_t cCfgItems, const char *pszName)
+{
+ PCTSTDEVCFGITEM pCfgItem = tstDevSsmFuzzGetCfgItem(paCfg, cCfgItems, pszName);
+ if ( pCfgItem
+ && pCfgItem->enmType == TSTDEVCFGITEMTYPE_INTEGER)
+ return (uint64_t)pCfgItem->u.i64;
+
+ return 0;
+}
+
+
+/**
+ * Entry point for the SSM fuzzer.
+ *
+ * @returns VBox status code.
+ * @param hDut The device under test.
+ * @param paCfg The testcase config.
+ * @param cCfgItems Number of config items.
+ */
+static DECLCALLBACK(int) tstDevIoFuzzEntry(TSTDEVDUT hDut, PCTSTDEVCFGITEM paCfg, uint32_t cCfgItems)
+{
+ /* Determine the amount of I/O port handlers. */
+ uint32_t cIoPortRegs = 0;
+ PRTDEVDUTIOPORT pIoPort;
+ RTListForEach(&hDut->LstIoPorts, pIoPort, RTDEVDUTIOPORT, NdIoPorts)
+ {
+ cIoPortRegs++;
+ }
+
+ /* Determine the amount of MMIO regions. */
+ uint32_t cMmioRegions = 0;
+ PRTDEVDUTMMIO pMmio;
+ RTListForEach(&hDut->LstMmio, pMmio, RTDEVDUTMMIO, NdMmio)
+ {
+ cMmioRegions++;
+ }
+
+ RTRAND hRnd;
+ int rc = RTRandAdvCreateParkMiller(&hRnd);
+ if (RT_SUCCESS(rc))
+ {
+ RTRandAdvSeed(hRnd, 0x123456789);
+ uint64_t cRuntimeMs = tstDevSsmFuzzGetCfgU64(paCfg, cCfgItems, "RuntimeSec") * RT_MS_1SEC_64;
+ uint64_t tsStart = RTTimeMilliTS();
+ uint64_t cFuzzedInputs = 0;
+ RTCritSectEnter(&hDut->pDevIns->pCritSectRoR3->s.CritSect);
+ do
+ {
+ bool fMmio = false;
+
+ if ( cMmioRegions
+ && !cIoPortRegs)
+ fMmio = true;
+ else if ( !cMmioRegions
+ && cIoPortRegs)
+ fMmio = false;
+ else
+ fMmio = RT_BOOL(RTRandAdvU32Ex(hRnd, 0, 1));
+
+ if (fMmio)
+ {
+ uint32_t iMmio = RTRandAdvU32Ex(hRnd, 0, cMmioRegions - 1);
+ RTListForEach(&hDut->LstMmio, pMmio, RTDEVDUTMMIO, NdMmio)
+ {
+ if (!iMmio)
+ break;
+ iMmio--;
+ }
+
+ uint32_t uMin = pMmio->pfnWriteR3 ? 0 : 1;
+ uint32_t uMax = pMmio->pfnReadR3 ? 1 : 0;
+
+ RTGCPHYS offRegion = RTRandAdvU64Ex(hRnd, 0, pMmio->cbRegion);
+ bool fRead = RT_BOOL(uMin == uMax ? uMin : RTRandAdvU32Ex(hRnd, uMin, uMax));
+ bool fRing0 = false;
+
+ if ( ( fRead
+ && pMmio->pfnReadR0)
+ || ( !fRead
+ && pMmio->pfnWriteR0))
+ fRing0 = RT_BOOL(RTRandAdvU32Ex(hRnd, 0, 1));
+
+ uint64_t u64Value = fRead ? 0 : RTRandAdvU64(hRnd);
+ uint32_t cbValue = g_aAccWidths[RTRandAdvU32Ex(hRnd, 0, 3)];
+
+ if (fRead)
+ {
+ if (fRing0)
+ {
+ VBOXSTRICTRC rcStrict = pMmio->pfnReadR0((PPDMDEVINS)hDut->pDevInsR0, pIoPort->pvUserR0, offRegion, &u64Value, cbValue);
+ if (VBOXSTRICTRC_VAL(rcStrict) == VINF_IOM_R3_MMIO_READ)
+ {
+ AssertRelease(pMmio->pfnReadR3);
+ pMmio->pfnReadR3(hDut->pDevIns, pIoPort->pvUserR3, offRegion, &u64Value, cbValue);
+ }
+
+ }
+ else
+ pMmio->pfnReadR3(hDut->pDevIns, pMmio->pvUserR3, offRegion, &u64Value, cbValue);
+ }
+ else
+ {
+ if (fRing0)
+ {
+ VBOXSTRICTRC rcStrict = pMmio->pfnWriteR0((PPDMDEVINS)hDut->pDevInsR0, pIoPort->pvUserR0, offRegion, &u64Value, cbValue);
+ if (VBOXSTRICTRC_VAL(rcStrict) == VINF_IOM_R3_MMIO_WRITE)
+ {
+ AssertRelease(pMmio->pfnWriteR3);
+ pMmio->pfnWriteR3(hDut->pDevIns, pIoPort->pvUserR3, offRegion, &u64Value, cbValue);
+ }
+
+ }
+ else
+ pMmio->pfnWriteR3(hDut->pDevIns, pMmio->pvUserR3, offRegion, &u64Value, cbValue);
+ }
+ }
+ else
+ {
+ uint32_t iIoPort = RTRandAdvU32Ex(hRnd, 0, cIoPortRegs - 1);
+ RTListForEach(&hDut->LstIoPorts, pIoPort, RTDEVDUTIOPORT, NdIoPorts)
+ {
+ if (!iIoPort)
+ break;
+ iIoPort--;
+ }
+
+ uint32_t uMin = pIoPort->pfnOutR3 ? 0 : 1;
+ uint32_t uMax = pIoPort->pfnInR3 ? 1 : 0;
+
+ uint32_t offPort = RTRandAdvU32Ex(hRnd, 0, pIoPort->cPorts);
+ bool fRead = RT_BOOL(uMin == uMax ? uMin : RTRandAdvU32Ex(hRnd, uMin, uMax));
+ bool fRing0 = false;
+
+ if ( ( fRead
+ && pIoPort->pfnInR0)
+ || ( !fRead
+ && pIoPort->pfnOutR3))
+ fRing0 = RT_BOOL(RTRandAdvU32Ex(hRnd, 0, 1));
+
+ uint32_t u32Value = fRead ? 0 : RTRandAdvU32(hRnd);
+ uint32_t cbValue = g_aAccWidths[RTRandAdvU32Ex(hRnd, 0, 2)];
+
+ if (fRead)
+ {
+ if (fRing0)
+ {
+ VBOXSTRICTRC rcStrict = pIoPort->pfnInR0((PPDMDEVINS)hDut->pDevInsR0, pIoPort->pvUserR0, offPort, &u32Value, cbValue);
+ if (VBOXSTRICTRC_VAL(rcStrict) == VINF_IOM_R3_IOPORT_READ)
+ {
+ AssertRelease(pIoPort->pfnInR3);
+ pIoPort->pfnInR3(hDut->pDevIns, pIoPort->pvUserR3, offPort, &u32Value, cbValue);
+ }
+
+ }
+ else
+ pIoPort->pfnInR3(hDut->pDevIns, pIoPort->pvUserR3, offPort, &u32Value, cbValue);
+ }
+ else
+ {
+ if (fRing0)
+ {
+ VBOXSTRICTRC rcStrict = pIoPort->pfnOutR0((PPDMDEVINS)hDut->pDevInsR0, pIoPort->pvUserR0, offPort, u32Value, cbValue);
+ if (VBOXSTRICTRC_VAL(rcStrict) == VINF_IOM_R3_IOPORT_WRITE)
+ {
+ AssertRelease(pIoPort->pfnOutR3);
+ pIoPort->pfnOutR3(hDut->pDevIns, pIoPort->pvUserR3, offPort, u32Value, cbValue);
+ }
+
+ }
+ else
+ pIoPort->pfnOutR3(hDut->pDevIns, pIoPort->pvUserR3, offPort, u32Value, cbValue);
+ }
+ }
+
+ cFuzzedInputs++;
+ } while ( RT_SUCCESS(rc)
+ && RTTimeMilliTS() - tsStart < cRuntimeMs);
+ RTCritSectLeave(&hDut->pDevIns->pCritSectRoR3->s.CritSect);
+
+ RTPrintf("Fuzzed inputs: %u\n", cFuzzedInputs);
+ RTRandAdvDestroy(hRnd);
+ }
+
+ return rc;
+}
+
+
+const TSTDEVTESTCASEREG g_TestcaseIoFuzz =
+{
+ /** szName */
+ "IoFuzz",
+ /** pszDesc */
+ "Fuzzes devices I/O handlers",
+ /** fFlags */
+ 0,
+ /** pfnTestEntry */
+ tstDevIoFuzzEntry
+};
+
diff --git a/src/VBox/Devices/testcase/tstDevicePdmDevHlp.cpp b/src/VBox/Devices/testcase/tstDevicePdmDevHlp.cpp
new file mode 100644
index 00000000..0c4d54d9
--- /dev/null
+++ b/src/VBox/Devices/testcase/tstDevicePdmDevHlp.cpp
@@ -0,0 +1,6196 @@
+/* $Id: tstDevicePdmDevHlp.cpp $ */
+/** @file
+ * tstDevice - Test framework for PDM devices/drivers, PDM helper implementation.
+ */
+
+/*
+ * Copyright (C) 2017-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEFAULT /** @todo */
+#include <VBox/types.h>
+#include <VBox/version.h>
+#include <VBox/vmm/pdmpci.h>
+
+#include <iprt/assert.h>
+#include <iprt/mem.h>
+#include <iprt/rand.h>
+
+#include "tstDeviceInternal.h"
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+
+/* Temporarily until the stubs got implemented. */
+#define VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS 1
+
+/** @def PDMDEV_ASSERT_DEVINS
+ * Asserts the validity of the device instance.
+ */
+#ifdef VBOX_STRICT
+# define PDMDEV_ASSERT_DEVINS(pDevIns) \
+ do { \
+ AssertPtr(pDevIns); \
+ Assert(pDevIns->u32Version == PDM_DEVINS_VERSION); \
+ Assert(pDevIns->CTX_SUFF(pvInstanceDataFor) == (void *)&pDevIns->achInstanceData[0]); \
+ } while (0)
+#else
+# define PDMDEV_ASSERT_DEVINS(pDevIns) do { } while (0)
+#endif
+
+
+/** Frequency of the real clock. */
+#define TMCLOCK_FREQ_REAL UINT32_C(1000)
+/** Frequency of the virtual clock. */
+#define TMCLOCK_FREQ_VIRTUAL UINT32_C(1000000000)
+
+
+/** Start structure magic. (Isaac Asimov) */
+#define SSMR3STRUCT_BEGIN UINT32_C(0x19200102)
+/** End structure magic. (Isaac Asimov) */
+#define SSMR3STRUCT_END UINT32_C(0x19920406)
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+
+
+
+/*********************************************************************************************************************************
+* Internal Functions *
+*********************************************************************************************************************************/
+
+
+/**
+ * Resolves a path reference to a configuration item.
+ *
+ * @returns VBox status code.
+ * @param paDevCfg The array of config items.
+ * @param cCfgItems Number of config items in the array.
+ * @param pszName Name of a byte string value.
+ * @param ppItem Where to store the pointer to the item.
+ */
+static int tstDev_CfgmR3ResolveItem(PCTSTDEVCFGITEM paDevCfg, uint32_t cCfgItems, const char *pszName, PCTSTDEVCFGITEM *ppItem)
+{
+ *ppItem = NULL;
+ if (!paDevCfg)
+ return VERR_CFGM_VALUE_NOT_FOUND;
+
+ size_t cchName = strlen(pszName);
+ PCTSTDEVCFGITEM pDevCfgItem = paDevCfg;
+
+ for (uint32_t i = 0; i < cCfgItems; i++)
+ {
+ size_t cchKey = strlen(pDevCfgItem->pszKey);
+ if (cchName == cchKey)
+ {
+ int iDiff = memcmp(pszName, pDevCfgItem->pszKey, cchName);
+ if (iDiff <= 0)
+ {
+ if (iDiff != 0)
+ break;
+ *ppItem = pDevCfgItem;
+ return VINF_SUCCESS;
+ }
+ }
+
+ /* next */
+ pDevCfgItem++;
+ }
+ return VERR_CFGM_VALUE_NOT_FOUND;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortCreateEx} */
+static DECLCALLBACK(int) pdmR3DevHlp_IoPortCreateEx(PPDMDEVINS pDevIns, RTIOPORT cPorts, uint32_t fFlags, PPDMPCIDEV pPciDev,
+ uint32_t iPciRegion, PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
+ PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr, RTR3PTR pvUser,
+ const char *pszDesc, PCIOMIOPORTDESC paExtDescs, PIOMIOPORTHANDLE phIoPorts)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_IoPortCreateEx: caller='%s'/%d: cPorts=%#x fFlags=%#x pPciDev=%p iPciRegion=%#x pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p pvUser=%p pszDesc=%p:{%s} paExtDescs=%p phIoPorts=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, cPorts, fFlags, pPciDev, iPciRegion, pfnOut, pfnIn, pfnOutStr, pfnInStr,
+ pvUser, pszDesc, pszDesc, paExtDescs, phIoPorts));
+
+ /** @todo Verify there is no overlapping. */
+
+ RT_NOREF(pszDesc);
+ int rc = VINF_SUCCESS;
+ PRTDEVDUTIOPORT pIoPort = (PRTDEVDUTIOPORT)RTMemAllocZ(sizeof(RTDEVDUTIOPORT));
+ if (RT_LIKELY(pIoPort))
+ {
+ pIoPort->cPorts = cPorts;
+ pIoPort->pvUserR3 = pvUser;
+ pIoPort->pfnOutR3 = pfnOut;
+ pIoPort->pfnInR3 = pfnIn;
+ pIoPort->pfnOutStrR3 = pfnOutStr;
+ pIoPort->pfnInStrR3 = pfnInStr;
+ RTListAppend(&pDevIns->Internal.s.pDut->LstIoPorts, &pIoPort->NdIoPorts);
+ *phIoPorts = (IOMIOPORTHANDLE)pIoPort;
+ }
+ else
+ rc = VERR_NO_MEMORY;
+
+ LogFlow(("pdmR3DevHlp_IoPortCreateEx: caller='%s'/%d: returns %Rrc (*phIoPorts=%#x)\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc, *phIoPorts));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortMap} */
+static DECLCALLBACK(int) pdmR3DevHlp_IoPortMap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts, RTIOPORT Port)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: hIoPorts=%#x Port=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts, Port));
+
+ PRTDEVDUTIOPORT pIoPort = (PRTDEVDUTIOPORT)hIoPorts;
+ pIoPort->PortStart = Port;
+
+ LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: returns VINF_SUCCESS\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortUnmap} */
+static DECLCALLBACK(int) pdmR3DevHlp_IoPortUnmap(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: hIoPorts=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts));
+
+ PRTDEVDUTIOPORT pIoPort = (PRTDEVDUTIOPORT)hIoPorts;
+ pIoPort->PortStart = 0;
+ int rc = VINF_SUCCESS;
+
+ LogFlow(("pdmR3DevHlp_IoPortMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortGetMappingAddress} */
+static DECLCALLBACK(uint32_t) pdmR3DevHlp_IoPortGetMappingAddress(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_IoPortGetMappingAddress: caller='%s'/%d: hIoPorts=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts));
+
+ PRTDEVDUTIOPORT pIoPort = (PRTDEVDUTIOPORT)hIoPorts;
+ uint32_t uAddress = pIoPort->PortStart;
+
+ LogFlow(("pdmR3DevHlp_IoPortGetMappingAddress: caller='%s'/%d: returns %#RX32\n", pDevIns->pReg->szName, pDevIns->iInstance, uAddress));
+ return uAddress;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnIoPortWrite} */
+static DECLCALLBACK(VBOXSTRICTRC) pdmR3DevHlp_IoPortWrite(PPDMDEVINS pDevIns, RTIOPORT Port, uint32_t u32Value, size_t cbValue)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_IoPortWrite: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
+
+ RT_NOREF(Port, u32Value, cbValue);
+ VBOXSTRICTRC rcStrict = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_IoPortWrite: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict)));
+ return rcStrict;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMmioCreateEx} */
+static DECLCALLBACK(int) pdmR3DevHlp_MmioCreateEx(PPDMDEVINS pDevIns, RTGCPHYS cbRegion,
+ uint32_t fFlags, PPDMPCIDEV pPciDev, uint32_t iPciRegion,
+ PFNIOMMMIONEWWRITE pfnWrite, PFNIOMMMIONEWREAD pfnRead, PFNIOMMMIONEWFILL pfnFill,
+ void *pvUser, const char *pszDesc, PIOMMMIOHANDLE phRegion)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_MmioCreateEx: caller='%s'/%d: cbRegion=%#RGp fFlags=%#x pPciDev=%p iPciRegion=%#x pfnWrite=%p pfnRead=%p pfnFill=%p pvUser=%p pszDesc=%p:{%s} phRegion=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, fFlags, pPciDev, iPciRegion, pfnWrite, pfnRead, pfnFill, pvUser, pszDesc, pszDesc, phRegion));
+
+ /** @todo Verify there is no overlapping. */
+
+ RT_NOREF(pszDesc);
+ int rc = VINF_SUCCESS;
+ PRTDEVDUTMMIO pMmio = (PRTDEVDUTMMIO)RTMemAllocZ(sizeof(*pMmio));
+ if (RT_LIKELY(pMmio))
+ {
+ pMmio->cbRegion = cbRegion;
+ pMmio->pvUserR3 = pvUser;
+ pMmio->pfnWriteR3 = pfnWrite;
+ pMmio->pfnReadR3 = pfnRead;
+ pMmio->pfnFillR3 = pfnFill;
+ RTListAppend(&pDevIns->Internal.s.pDut->LstMmio, &pMmio->NdMmio);
+ *phRegion = (IOMMMIOHANDLE)pMmio;
+ }
+ else
+ rc = VERR_NO_MEMORY;
+
+ LogFlow(("pdmR3DevHlp_MmioCreateEx: caller='%s'/%d: returns %Rrc (*phRegion=%#x)\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc, *phRegion));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMmioMap} */
+static DECLCALLBACK(int) pdmR3DevHlp_MmioMap(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS GCPhys)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_MmioMap: caller='%s'/%d: hRegion=%#x GCPhys=%#RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion, GCPhys));
+
+ int rc = VINF_SUCCESS;
+ PRTDEVDUTMMIO pMmio = (PRTDEVDUTMMIO)hRegion;
+ pMmio->GCPhysStart = GCPhys;
+
+ LogFlow(("pdmR3DevHlp_MmioMap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMmioUnmap} */
+static DECLCALLBACK(int) pdmR3DevHlp_MmioUnmap(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_MmioUnmap: caller='%s'/%d: hRegion=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion));
+
+ int rc = VINF_SUCCESS;
+ PRTDEVDUTMMIO pMmio = (PRTDEVDUTMMIO)hRegion;
+ pMmio->GCPhysStart = NIL_RTGCPHYS;
+
+ LogFlow(("pdmR3DevHlp_MmioUnmap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMmioReduce} */
+static DECLCALLBACK(int) pdmR3DevHlp_MmioReduce(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS cbRegion)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_MmioReduce: caller='%s'/%d: hRegion=%#x cbRegion=%#RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion, cbRegion));
+
+ int rc = VINF_SUCCESS;
+ PRTDEVDUTMMIO pMmio = (PRTDEVDUTMMIO)hRegion;
+ pMmio->cbRegion = cbRegion;
+
+ LogFlow(("pdmR3DevHlp_MmioReduce: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMmioGetMappingAddress} */
+static DECLCALLBACK(RTGCPHYS) pdmR3DevHlp_MmioGetMappingAddress(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_MmioGetMappingAddress: caller='%s'/%d: hRegion=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion));
+
+ PRTDEVDUTMMIO pMmio = (PRTDEVDUTMMIO)hRegion;
+ RTGCPHYS GCPhys = pMmio->GCPhysStart;
+
+ LogFlow(("pdmR3DevHlp_MmioGetMappingAddress: caller='%s'/%d: returns %RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, GCPhys));
+ return GCPhys;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMmio2Create} */
+static DECLCALLBACK(int) pdmR3DevHlp_Mmio2Create(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iPciRegion, RTGCPHYS cbRegion,
+ uint32_t fFlags, const char *pszDesc, void **ppvMapping, PPGMMMIO2HANDLE phRegion)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_Mmio2Create: caller='%s'/%d: pPciDev=%p (%#x) iPciRegion=%#x cbRegion=%#RGp fFlags=%RX32 pszDesc=%p:{%s} ppvMapping=%p phRegion=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev ? pPciDev->uDevFn : UINT32_MAX, iPciRegion, cbRegion,
+ fFlags, pszDesc, pszDesc, ppvMapping, phRegion));
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+ *phRegion = 0;
+ *ppvMapping = RTMemAllocZ(cbRegion);
+ if (!*ppvMapping)
+ rc = VERR_NO_MEMORY;
+#endif
+
+ LogFlow(("pdmR3DevHlp_Mmio2Create: caller='%s'/%d: returns %Rrc *ppvMapping=%p phRegion=%#RX64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc, *ppvMapping, *phRegion));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMmio2Destroy} */
+static DECLCALLBACK(int) pdmR3DevHlp_Mmio2Destroy(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_Mmio2Destroy: caller='%s'/%d: hRegion=%#RX64\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_Mmio2Destroy: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMmio2Map} */
+static DECLCALLBACK(int) pdmR3DevHlp_Mmio2Map(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, RTGCPHYS GCPhys)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_Mmio2Map: caller='%s'/%d: hRegion=%#RX64 GCPhys=%RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion, GCPhys));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_Mmio2Map: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMmio2Unmap} */
+static DECLCALLBACK(int) pdmR3DevHlp_Mmio2Unmap(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_Mmio2Unmap: caller='%s'/%d: hRegion=%#RX64\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_Mmio2Unmap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMmio2Reduce} */
+static DECLCALLBACK(int) pdmR3DevHlp_Mmio2Reduce(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, RTGCPHYS cbRegion)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_Mmio2Reduce: caller='%s'/%d: hRegion=%#RX64 cbRegion=%RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion, cbRegion));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_Mmio2Reduce: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMmio2GetMappingAddress} */
+static DECLCALLBACK(RTGCPHYS) pdmR3DevHlp_Mmio2GetMappingAddress(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_Mmio2GetMappingAddress: caller='%s'/%d: hRegion=%#RX6r\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion));
+
+ RTGCPHYS GCPhys = NIL_RTGCPHYS;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_Mmio2GetMappingAddress: caller='%s'/%d: returns %RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, GCPhys));
+ return GCPhys;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMmio2QueryAndResetDirtyBitmap} */
+static DECLCALLBACK(int) pdmR3DevHlp_Mmio2QueryAndResetDirtyBitmap(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion,
+ void *pvBitmap, size_t cbBitmap)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ //PVM pVM = pDevIns->Internal.s.pVMR3;
+ LogFlow(("pdmR3DevHlp_Mmio2QueryAndResetDirtyBitmap: caller='%s'/%d: hRegion=%#RX64 pvBitmap=%p cbBitmap=%#zx\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hRegion, pvBitmap, cbBitmap));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+
+ LogFlow(("pdmR3DevHlp_Mmio2QueryAndResetDirtyBitmap: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMmio2ControlDirtyPageTracking} */
+static DECLCALLBACK(int) pdmR3DevHlp_Mmio2ControlDirtyPageTracking(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, bool fEnabled)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ //PVM pVM = pDevIns->Internal.s.pVMR3;
+ LogFlow(("pdmR3DevHlp_Mmio2ControlDirtyPageTracking: caller='%s'/%d: hRegion=%#RX64 fEnabled=%RTbool\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hRegion, fEnabled));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+
+ LogFlow(("pdmR3DevHlp_Mmio2ControlDirtyPageTracking: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnMmio2ChangeRegionNo
+ */
+static DECLCALLBACK(int) pdmR3DevHlp_Mmio2ChangeRegionNo(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion, uint32_t iNewRegion)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_Mmio2ChangeRegionNo: caller='%s'/%d: hRegion=%#RX6r iNewRegion=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, hRegion, iNewRegion));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_Mmio2ChangeRegionNo: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMmioMapMmio2Page} */
+static DECLCALLBACK(int) pdmR3DevHlp_MmioMapMmio2Page(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS offRegion,
+ uint64_t hMmio2, RTGCPHYS offMmio2, uint64_t fPageFlags)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_MmioMapMmio2Page: caller='%s'/%d: hRegion=%RX64 offRegion=%RGp hMmio2=%RX64 offMmio2=%RGp fPageFlags=%RX64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hRegion, offRegion, hMmio2, offMmio2, fPageFlags));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ Log(("pdmR3DevHlp_MmioMapMmio2Page: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMmioResetRegion} */
+static DECLCALLBACK(int) pdmR3DevHlp_MmioResetRegion(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_MmioResetRegion: caller='%s'/%d: hRegion=%RX64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hRegion));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ Log(("pdmR3DevHlp_MmioResetRegion: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnROMRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_ROMRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange,
+ const void *pvBinary, uint32_t cbBinary, uint32_t fFlags, const char *pszDesc)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: GCPhysStart=%RGp cbRange=%#x pvBinary=%p cbBinary=%#x fFlags=%#RX32 pszDesc=%p:{%s}\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, GCPhysStart, cbRange, pvBinary, cbBinary, fFlags, pszDesc, pszDesc));
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_ROMRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnROMProtectShadow} */
+static DECLCALLBACK(int) pdmR3DevHlp_ROMProtectShadow(PPDMDEVINS pDevIns, RTGCPHYS GCPhysStart, uint32_t cbRange, PGMROMPROT enmProt)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: GCPhysStart=%RGp cbRange=%#x enmProt=%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, GCPhysStart, cbRange, enmProt));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_ROMProtectShadow: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMRegister(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)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: uVersion=%#x cbGuess=%#x pszBefore=%p:{%s}\n"
+ " pfnLivePrep=%p pfnLiveExec=%p pfnLiveVote=%p pfnSavePrep=%p pfnSaveExec=%p pfnSaveDone=%p pszLoadPrep=%p pfnLoadExec=%p pfnLoadDone=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, uVersion, cbGuess, pszBefore, pszBefore,
+ pfnLivePrep, pfnLiveExec, pfnLiveVote,
+ pfnSavePrep, pfnSaveExec, pfnSaveDone,
+ pfnLoadPrep, pfnLoadExec, pfnLoadDone));
+
+ RT_NOREF(cbGuess, pszBefore);
+ int rc = VINF_SUCCESS;
+ PTSTDEVDUTSSM pSsm = (PTSTDEVDUTSSM)RTMemAllocZ(sizeof(*pSsm));
+ if (RT_LIKELY(pSsm))
+ {
+ pSsm->uVersion = uVersion;
+ pSsm->pfnLivePrep = pfnLivePrep;
+ pSsm->pfnLiveExec = pfnLiveExec;
+ pSsm->pfnLiveVote = pfnLiveVote;
+ pSsm->pfnSavePrep = pfnSavePrep;
+ pSsm->pfnSaveExec = pfnSaveExec;
+ pSsm->pfnSaveDone = pfnSaveDone;
+ pSsm->pfnLoadPrep = pfnLoadPrep;
+ pSsm->pfnLoadExec = pfnLoadExec;
+ pSsm->pfnLoadDone = pfnLoadDone;
+ RTListAppend(&pDevIns->Internal.s.pDut->LstSsmHandlers, &pSsm->NdSsm);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+
+ LogFlow(("pdmR3DevHlp_SSMRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSSMRegisterLegacy} */
+static DECLCALLBACK(int) pdmR3DevHlp_SSMRegisterLegacy(PPDMDEVINS pDevIns, const char *pszOldName, PFNSSMDEVLOADPREP pfnLoadPrep,
+ PFNSSMDEVLOADEXEC pfnLoadExec, PFNSSMDEVLOADDONE pfnLoadDone)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SSMRegisterLegacy: caller='%s'/%d: pszOldName=%p:{%s} pfnLoadPrep=%p pfnLoadExec=%p pfnLoadDone=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pszOldName, pszOldName, pfnLoadPrep, pfnLoadExec, pfnLoadDone));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_SSMRegisterLegacy: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutStruct(PSSMHANDLE pSSM, const void *pvStruct, PCSSMFIELD paFields)
+{
+ RT_NOREF(pSSM, pvStruct, paFields);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutStructEx(PSSMHANDLE pSSM, const void *pvStruct, size_t cbStruct, uint32_t fFlags, PCSSMFIELD paFields, void *pvUser)
+{
+ RT_NOREF(pSSM, pvStruct, cbStruct, fFlags, paFields, pvUser);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutBool(PSSMHANDLE pSSM, bool fBool)
+{
+ RT_NOREF(pSSM, fBool);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutU8(PSSMHANDLE pSSM, uint8_t u8)
+{
+ RT_NOREF(pSSM, u8);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutS8(PSSMHANDLE pSSM, int8_t i8)
+{
+ RT_NOREF(pSSM, i8);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutU16(PSSMHANDLE pSSM, uint16_t u16)
+{
+ RT_NOREF(pSSM, u16);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutS16(PSSMHANDLE pSSM, int16_t i16)
+{
+ RT_NOREF(pSSM, i16);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutU32(PSSMHANDLE pSSM, uint32_t u32)
+{
+ RT_NOREF(pSSM, u32);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutS32(PSSMHANDLE pSSM, int32_t i32)
+{
+ RT_NOREF(pSSM, i32);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutU64(PSSMHANDLE pSSM, uint64_t u64)
+{
+ RT_NOREF(pSSM, u64);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutS64(PSSMHANDLE pSSM, int64_t i64)
+{
+ RT_NOREF(pSSM, i64);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutU128(PSSMHANDLE pSSM, uint128_t u128)
+{
+ RT_NOREF(pSSM, u128);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutS128(PSSMHANDLE pSSM, int128_t i128)
+{
+ RT_NOREF(pSSM, i128);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutUInt(PSSMHANDLE pSSM, RTUINT u)
+{
+ RT_NOREF(pSSM, u);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutSInt(PSSMHANDLE pSSM, RTINT i)
+{
+ RT_NOREF(pSSM, i);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutGCUInt(PSSMHANDLE pSSM, RTGCUINT u)
+{
+ RT_NOREF(pSSM, u);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutGCUIntReg(PSSMHANDLE pSSM, RTGCUINTREG u)
+{
+ RT_NOREF(pSSM, u);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutGCPhys32(PSSMHANDLE pSSM, RTGCPHYS32 GCPhys)
+{
+ RT_NOREF(pSSM, GCPhys);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutGCPhys64(PSSMHANDLE pSSM, RTGCPHYS64 GCPhys)
+{
+ RT_NOREF(pSSM, GCPhys);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutGCPhys(PSSMHANDLE pSSM, RTGCPHYS GCPhys)
+{
+ RT_NOREF(pSSM, GCPhys);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutGCPtr(PSSMHANDLE pSSM, RTGCPTR GCPtr)
+{
+ RT_NOREF(pSSM, GCPtr);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutGCUIntPtr(PSSMHANDLE pSSM, RTGCUINTPTR GCPtr)
+{
+ RT_NOREF(pSSM, GCPtr);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutRCPtr(PSSMHANDLE pSSM, RTRCPTR RCPtr)
+{
+ RT_NOREF(pSSM, RCPtr);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutIOPort(PSSMHANDLE pSSM, RTIOPORT IOPort)
+{
+ RT_NOREF(pSSM, IOPort);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutSel(PSSMHANDLE pSSM, RTSEL Sel)
+{
+ RT_NOREF(pSSM, Sel);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutMem(PSSMHANDLE pSSM, const void *pv, size_t cb)
+{
+ RT_NOREF(pSSM, pv, cb);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMPutStrZ(PSSMHANDLE pSSM, const char *psz)
+{
+ RT_NOREF(pSSM, psz);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * Gets the host bit count of the saved state.
+ *
+ * Works for on both save and load handles.
+ *
+ * @returns 32 or 64.
+ * @param pSSM The saved state handle.
+ */
+DECLINLINE(uint32_t) ssmR3GetHostBits(PSSMHANDLE pSSM)
+{
+ /** @todo Don't care about 32bit saved states for now (VBox is 64bit only as of 6.0). */
+ RT_NOREF(pSSM);
+ return HC_ARCH_BITS;
+}
+
+
+/**
+ * Saved state origins on a host using 32-bit MSC?
+ *
+ * Works for on both save and load handles.
+ *
+ * @returns true/false.
+ * @param pSSM The saved state handle.
+ */
+DECLINLINE(bool) ssmR3IsHostMsc32(PSSMHANDLE pSSM)
+{
+ /** @todo Don't care about 32bit saved states for now (VBox is 64bit only as of 6.0). */
+ RT_NOREF(pSSM);
+ return false;
+}
+
+
+/**
+ * Inlined worker that handles format checks and buffered reads.
+ *
+ * @param pSSM The saved state handle.
+ * @param pvBuf Where to store the read data.
+ * @param cbBuf Number of bytes to read.
+ */
+DECLINLINE(int) tstDevSsmR3DataRead(PSSMHANDLE pSSM, void *pvBuf, size_t cbBuf)
+{
+ /*
+ * Fend off previous errors and V1 data units.
+ */
+ if (RT_SUCCESS(pSSM->rc))
+ {
+ /** @todo Don't care about version 1 saved states (long obsolete). */
+ uint32_t off = pSSM->offDataBuffer;
+ if ( cbBuf <= pSSM->cbSavedState
+ && pSSM->cbSavedState - cbBuf >= off)
+ {
+ memcpy(pvBuf, &pSSM->pbSavedState[off], cbBuf);
+ pSSM->offDataBuffer = off + (uint32_t)cbBuf;
+ return VINF_SUCCESS;
+ }
+ else
+ pSSM->rc = VERR_BUFFER_OVERFLOW;
+ }
+ return pSSM->rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetBool(PSSMHANDLE pSSM, bool *pfBool)
+{
+ uint8_t u8; /* see SSMR3PutBool */
+ int rc = tstDevSsmR3DataRead(pSSM, &u8, sizeof(u8));
+ if (RT_SUCCESS(rc))
+ {
+ Assert(u8 <= 1);
+ *pfBool = RT_BOOL(u8);
+ }
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetBoolV(PSSMHANDLE pSSM, bool volatile *pfBool)
+{
+ uint8_t u8; /* see SSMR3PutBool */
+ int rc = tstDevSsmR3DataRead(pSSM, &u8, sizeof(u8));
+ if (RT_SUCCESS(rc))
+ {
+ Assert(u8 <= 1);
+ *pfBool = RT_BOOL(u8);
+ }
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetU8(PSSMHANDLE pSSM, uint8_t *pu8)
+{
+ return tstDevSsmR3DataRead(pSSM, pu8, sizeof(*pu8));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetU8V(PSSMHANDLE pSSM, uint8_t volatile *pu8)
+{
+ return tstDevSsmR3DataRead(pSSM, (void *)pu8, sizeof(*pu8));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetS8(PSSMHANDLE pSSM, int8_t *pi8)
+{
+ return tstDevSsmR3DataRead(pSSM, pi8, sizeof(*pi8));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetS8V(PSSMHANDLE pSSM, int8_t volatile *pi8)
+{
+ return tstDevSsmR3DataRead(pSSM, (void *)pi8, sizeof(*pi8));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetU16(PSSMHANDLE pSSM, uint16_t *pu16)
+{
+ return tstDevSsmR3DataRead(pSSM, pu16, sizeof(*pu16));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetU16V(PSSMHANDLE pSSM, uint16_t volatile *pu16)
+{
+ return tstDevSsmR3DataRead(pSSM, (void *)pu16, sizeof(*pu16));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetS16(PSSMHANDLE pSSM, int16_t *pi16)
+{
+ return tstDevSsmR3DataRead(pSSM, pi16, sizeof(*pi16));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetS16V(PSSMHANDLE pSSM, int16_t volatile *pi16)
+{
+ return tstDevSsmR3DataRead(pSSM, (void *)pi16, sizeof(*pi16));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetU32(PSSMHANDLE pSSM, uint32_t *pu32)
+{
+ return tstDevSsmR3DataRead(pSSM, pu32, sizeof(*pu32));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetU32V(PSSMHANDLE pSSM, uint32_t volatile *pu32)
+{
+ return tstDevSsmR3DataRead(pSSM, (void *)pu32, sizeof(*pu32));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetS32(PSSMHANDLE pSSM, int32_t *pi32)
+{
+ return tstDevSsmR3DataRead(pSSM, pi32, sizeof(*pi32));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetS32V(PSSMHANDLE pSSM, int32_t volatile *pi32)
+{
+ return tstDevSsmR3DataRead(pSSM, (void *)pi32, sizeof(*pi32));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetU64(PSSMHANDLE pSSM, uint64_t *pu64)
+{
+ return tstDevSsmR3DataRead(pSSM, pu64, sizeof(*pu64));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetU64V(PSSMHANDLE pSSM, uint64_t volatile *pu64)
+{
+ return tstDevSsmR3DataRead(pSSM, (void *)pu64, sizeof(*pu64));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetS64(PSSMHANDLE pSSM, int64_t *pi64)
+{
+ return tstDevSsmR3DataRead(pSSM, pi64, sizeof(*pi64));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetS64V(PSSMHANDLE pSSM, int64_t volatile *pi64)
+{
+ return tstDevSsmR3DataRead(pSSM, (void *)pi64, sizeof(*pi64));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetU128(PSSMHANDLE pSSM, uint128_t *pu128)
+{
+ return tstDevSsmR3DataRead(pSSM, pu128, sizeof(*pu128));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetU128V(PSSMHANDLE pSSM, uint128_t volatile *pu128)
+{
+ return tstDevSsmR3DataRead(pSSM, (void *)pu128, sizeof(*pu128));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetS128(PSSMHANDLE pSSM, int128_t *pi128)
+{
+ return tstDevSsmR3DataRead(pSSM, pi128, sizeof(*pi128));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetS128V(PSSMHANDLE pSSM, int128_t volatile *pi128)
+{
+ return tstDevSsmR3DataRead(pSSM, (void *)pi128, sizeof(*pi128));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetGCPhys32(PSSMHANDLE pSSM, PRTGCPHYS32 pGCPhys)
+{
+ return tstDevSsmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetGCPhys32V(PSSMHANDLE pSSM, RTGCPHYS32 volatile *pGCPhys)
+{
+ return tstDevSsmR3DataRead(pSSM, (void *)pGCPhys, sizeof(*pGCPhys));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetGCPhys64(PSSMHANDLE pSSM, PRTGCPHYS64 pGCPhys)
+{
+ return tstDevSsmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetGCPhys64V(PSSMHANDLE pSSM, RTGCPHYS64 volatile *pGCPhys)
+{
+ return tstDevSsmR3DataRead(pSSM, (void *)pGCPhys, sizeof(*pGCPhys));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetGCPhys(PSSMHANDLE pSSM, PRTGCPHYS pGCPhys)
+{
+ /*
+ * Default size?
+ */
+ if (RT_LIKELY(/*sizeof(*pGCPhys) == pSSM->u.Read.cbGCPhys*/true))
+ return tstDevSsmR3DataRead(pSSM, pGCPhys, sizeof(*pGCPhys));
+
+#if 0 /** @todo Later if necessary (only very old saved states). */
+ /*
+ * Fiddly.
+ */
+ Assert(sizeof(*pGCPhys) == sizeof(uint64_t) || sizeof(*pGCPhys) == sizeof(uint32_t));
+ Assert(pSSM->u.Read.cbGCPhys == sizeof(uint64_t) || pSSM->u.Read.cbGCPhys == sizeof(uint32_t));
+ if (pSSM->u.Read.cbGCPhys == sizeof(uint64_t))
+ {
+ /* 64-bit saved, 32-bit load: try truncate it. */
+ uint64_t u64;
+ int rc = tstDevSsmR3DataRead(pSSM, &u64, sizeof(uint64_t));
+ if (RT_FAILURE(rc))
+ return rc;
+ if (u64 >= _4G)
+ return VERR_SSM_GCPHYS_OVERFLOW;
+ *pGCPhys = (RTGCPHYS)u64;
+ return rc;
+ }
+
+ /* 32-bit saved, 64-bit load: clear the high part. */
+ *pGCPhys = 0;
+ return tstDevSsmR3DataRead(pSSM, pGCPhys, sizeof(uint32_t));
+#endif
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetGCPhysV(PSSMHANDLE pSSM, RTGCPHYS volatile *pGCPhys)
+{
+ return pdmR3DevHlp_SSMGetGCPhys(pSSM, (PRTGCPHYS)pGCPhys);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetUInt(PSSMHANDLE pSSM, PRTUINT pu)
+{
+ return tstDevSsmR3DataRead(pSSM, pu, sizeof(*pu));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetSInt(PSSMHANDLE pSSM, PRTINT pi)
+{
+ return tstDevSsmR3DataRead(pSSM, pi, sizeof(*pi));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetGCPtr(PSSMHANDLE pSSM, PRTGCPTR pGCPtr)
+{
+ return tstDevSsmR3DataRead(pSSM, pGCPtr, sizeof(*pGCPtr));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetGCUInt(PSSMHANDLE pSSM, PRTGCUINT pu)
+{
+ return pdmR3DevHlp_SSMGetGCPtr(pSSM, (PRTGCPTR)pu);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetGCUIntReg(PSSMHANDLE pSSM, PRTGCUINTREG pu)
+{
+ AssertCompile(sizeof(RTGCPTR) == sizeof(*pu));
+ return pdmR3DevHlp_SSMGetGCPtr(pSSM, (PRTGCPTR)pu);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetGCUIntPtr(PSSMHANDLE pSSM, PRTGCUINTPTR pGCPtr)
+{
+ return pdmR3DevHlp_SSMGetGCPtr(pSSM, (PRTGCPTR)pGCPtr);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetRCPtr(PSSMHANDLE pSSM, PRTRCPTR pRCPtr)
+{
+ return tstDevSsmR3DataRead(pSSM, pRCPtr, sizeof(*pRCPtr));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetIOPort(PSSMHANDLE pSSM, PRTIOPORT pIOPort)
+{
+ return tstDevSsmR3DataRead(pSSM, pIOPort, sizeof(*pIOPort));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetSel(PSSMHANDLE pSSM, PRTSEL pSel)
+{
+ return tstDevSsmR3DataRead(pSSM, pSel, sizeof(*pSel));
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetMem(PSSMHANDLE pSSM, void *pv, size_t cb)
+{
+ return tstDevSsmR3DataRead(pSSM, pv, cb);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetStrZEx(PSSMHANDLE pSSM, char *psz, size_t cbMax, size_t *pcbStr)
+{
+ /* read size prefix. */
+ uint32_t u32;
+ int rc = pdmR3DevHlp_SSMGetU32(pSSM, &u32);
+ if (RT_SUCCESS(rc))
+ {
+ if (pcbStr)
+ *pcbStr = u32;
+ if (u32 < cbMax)
+ {
+ /* terminate and read string content. */
+ psz[u32] = '\0';
+ return tstDevSsmR3DataRead(pSSM, psz, u32);
+ }
+ return VERR_TOO_MUCH_DATA;
+ }
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetStrZ(PSSMHANDLE pSSM, char *psz, size_t cbMax)
+{
+ return pdmR3DevHlp_SSMGetStrZEx(pSSM, psz, cbMax, NULL);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMSkip(PSSMHANDLE pSSM, size_t cb)
+{
+ while (cb > 0)
+ {
+ uint8_t abBuf[8192];
+ size_t cbCur = RT_MIN(sizeof(abBuf), cb);
+ cb -= cbCur;
+ int rc = tstDevSsmR3DataRead(pSSM, abBuf, cbCur);
+ if (RT_FAILURE(rc))
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetStruct(PSSMHANDLE pSSM, void *pvStruct, PCSSMFIELD paFields)
+{
+ AssertPtr(pvStruct);
+ AssertPtr(paFields);
+
+ /* begin marker. */
+ uint32_t u32Magic;
+ int rc = pdmR3DevHlp_SSMGetU32(pSSM, &u32Magic);
+ if (RT_FAILURE(rc))
+ return rc;
+ AssertMsgReturn(u32Magic == SSMR3STRUCT_BEGIN, ("u32Magic=%#RX32\n", u32Magic), pSSM->rc = VERR_SSM_STRUCTURE_MAGIC);
+
+ /* get the fields */
+ for (PCSSMFIELD pCur = paFields;
+ pCur->cb != UINT32_MAX && pCur->off != UINT32_MAX;
+ pCur++)
+ {
+ if (pCur->uFirstVer <= pSSM->uCurUnitVer)
+ {
+ uint8_t *pbField = (uint8_t *)pvStruct + pCur->off;
+ switch ((uintptr_t)pCur->pfnGetPutOrTransformer)
+ {
+ case SSMFIELDTRANS_NO_TRANSFORMATION:
+ rc = tstDevSsmR3DataRead(pSSM, pbField, pCur->cb);
+ break;
+
+ case SSMFIELDTRANS_GCPTR:
+ AssertMsgBreakStmt(pCur->cb == sizeof(RTGCPTR), ("%#x (%s)\n", pCur->cb, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = pdmR3DevHlp_SSMGetGCPtr(pSSM, (PRTGCPTR)pbField);
+ break;
+
+ case SSMFIELDTRANS_GCPHYS:
+ AssertMsgBreakStmt(pCur->cb == sizeof(RTGCPHYS), ("%#x (%s)\n", pCur->cb, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = pdmR3DevHlp_SSMGetGCPhys(pSSM, (PRTGCPHYS)pbField);
+ break;
+
+ case SSMFIELDTRANS_RCPTR:
+ AssertMsgBreakStmt(pCur->cb == sizeof(RTRCPTR), ("%#x (%s)\n", pCur->cb, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = pdmR3DevHlp_SSMGetRCPtr(pSSM, (PRTRCPTR)pbField);
+ break;
+
+ case SSMFIELDTRANS_RCPTR_ARRAY:
+ {
+ uint32_t const cEntries = pCur->cb / sizeof(RTRCPTR);
+ AssertMsgBreakStmt(pCur->cb == cEntries * sizeof(RTRCPTR) && cEntries, ("%#x (%s)\n", pCur->cb, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = VINF_SUCCESS;
+ for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
+ rc = pdmR3DevHlp_SSMGetRCPtr(pSSM, &((PRTRCPTR)pbField)[i]);
+ break;
+ }
+
+ default:
+ AssertMsgFailedBreakStmt(("%#x\n", pCur->pfnGetPutOrTransformer), rc = VERR_SSM_FIELD_COMPLEX);
+ }
+ if (RT_FAILURE(rc))
+ {
+ if (RT_SUCCESS(pSSM->rc))
+ pSSM->rc = rc;
+ return rc;
+ }
+ }
+ }
+
+ /* end marker */
+ rc = pdmR3DevHlp_SSMGetU32(pSSM, &u32Magic);
+ if (RT_FAILURE(rc))
+ return rc;
+ AssertMsgReturn(u32Magic == SSMR3STRUCT_END, ("u32Magic=%#RX32\n", u32Magic), pSSM->rc = VERR_SSM_STRUCTURE_MAGIC);
+ return rc;
+}
+
+
+/**
+ * SSMR3GetStructEx helper that gets a HCPTR that is used as a NULL indicator.
+ *
+ * @returns VBox status code.
+ *
+ * @param pSSM The saved state handle.
+ * @param ppv Where to return the value (0/1).
+ * @param fFlags SSMSTRUCT_FLAGS_XXX.
+ */
+DECLINLINE(int) ssmR3GetHCPtrNI(PSSMHANDLE pSSM, void **ppv, uint32_t fFlags)
+{
+ uintptr_t uPtrNI;
+ if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
+ {
+ if (ssmR3GetHostBits(pSSM) == 64)
+ {
+ uint64_t u;
+ int rc = tstDevSsmR3DataRead(pSSM, &u, sizeof(u));
+ if (RT_FAILURE(rc))
+ return rc;
+ uPtrNI = u ? 1 : 0;
+ }
+ else
+ {
+ uint32_t u;
+ int rc = tstDevSsmR3DataRead(pSSM, &u, sizeof(u));
+ if (RT_FAILURE(rc))
+ return rc;
+ uPtrNI = u ? 1 : 0;
+ }
+ }
+ else
+ {
+ bool f;
+ int rc = pdmR3DevHlp_SSMGetBool(pSSM, &f);
+ if (RT_FAILURE(rc))
+ return rc;
+ uPtrNI = f ? 1 : 0;
+ }
+ *ppv = (void *)uPtrNI;
+ return VINF_SUCCESS;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMGetStructEx(PSSMHANDLE pSSM, void *pvStruct, size_t cbStruct, uint32_t fFlags, PCSSMFIELD paFields, void *pvUser)
+{
+ int rc;
+ uint32_t u32Magic;
+
+ /*
+ * Validation.
+ */
+ AssertMsgReturn(!(fFlags & ~SSMSTRUCT_FLAGS_VALID_MASK), ("%#x\n", fFlags), pSSM->rc = VERR_INVALID_PARAMETER);
+ AssertPtr(pvStruct);
+ AssertPtr(paFields);
+
+ /*
+ * Begin marker.
+ */
+ if (!(fFlags & (SSMSTRUCT_FLAGS_NO_MARKERS | SSMSTRUCT_FLAGS_NO_LEAD_MARKER)))
+ {
+ rc = pdmR3DevHlp_SSMGetU32(pSSM, &u32Magic);
+ if (RT_FAILURE(rc))
+ return rc;
+ AssertMsgReturn(u32Magic == SSMR3STRUCT_BEGIN, ("u32Magic=%#RX32\n", u32Magic), pSSM->rc = VERR_SSM_STRUCTURE_MAGIC);
+ }
+
+ /*
+ * Put the fields
+ */
+ rc = VINF_SUCCESS;
+ uint32_t off = 0;
+ for (PCSSMFIELD pCur = paFields;
+ pCur->cb != UINT32_MAX && pCur->off != UINT32_MAX;
+ pCur++)
+ {
+ uint32_t const offField = (!SSMFIELDTRANS_IS_PADDING(pCur->pfnGetPutOrTransformer) || pCur->off != UINT32_MAX / 2)
+ && !SSMFIELDTRANS_IS_OLD(pCur->pfnGetPutOrTransformer)
+ ? pCur->off
+ : off;
+ uint32_t const cbField = SSMFIELDTRANS_IS_OLD(pCur->pfnGetPutOrTransformer)
+ ? 0
+ : SSMFIELDTRANS_IS_PADDING(pCur->pfnGetPutOrTransformer)
+ ? RT_HIWORD(pCur->cb)
+ : pCur->cb;
+ AssertMsgReturn( cbField <= cbStruct
+ && offField + cbField <= cbStruct
+ && offField + cbField >= offField,
+ ("off=%#x cb=%#x cbStruct=%#x (%s)\n", cbField, offField, cbStruct, pCur->pszName),
+ pSSM->rc = VERR_SSM_FIELD_OUT_OF_BOUNDS);
+ AssertMsgReturn( !(fFlags & SSMSTRUCT_FLAGS_FULL_STRUCT)
+ || off == offField,
+ ("off=%#x offField=%#x (%s)\n", off, offField, pCur->pszName),
+ pSSM->rc = VERR_SSM_FIELD_NOT_CONSECUTIVE);
+
+ if (pCur->uFirstVer <= pSSM->uCurUnitVer)
+ {
+ rc = VINF_SUCCESS;
+ uint8_t *pbField = (uint8_t *)pvStruct + offField;
+ switch ((uintptr_t)pCur->pfnGetPutOrTransformer)
+ {
+ case SSMFIELDTRANS_NO_TRANSFORMATION:
+ rc = tstDevSsmR3DataRead(pSSM, pbField, cbField);
+ break;
+
+ case SSMFIELDTRANS_GCPHYS:
+ AssertMsgBreakStmt(cbField == sizeof(RTGCPHYS), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = pdmR3DevHlp_SSMGetGCPhys(pSSM, (PRTGCPHYS)pbField);
+ break;
+
+ case SSMFIELDTRANS_GCPTR:
+ AssertMsgBreakStmt(cbField == sizeof(RTGCPTR), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = pdmR3DevHlp_SSMGetGCPtr(pSSM, (PRTGCPTR)pbField);
+ break;
+
+ case SSMFIELDTRANS_RCPTR:
+ AssertMsgBreakStmt(cbField == sizeof(RTRCPTR), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = pdmR3DevHlp_SSMGetRCPtr(pSSM, (PRTRCPTR)pbField);
+ break;
+
+ case SSMFIELDTRANS_RCPTR_ARRAY:
+ {
+ uint32_t const cEntries = cbField / sizeof(RTRCPTR);
+ AssertMsgBreakStmt(cbField == cEntries * sizeof(RTRCPTR) && cEntries, ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = VINF_SUCCESS;
+ for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
+ rc = pdmR3DevHlp_SSMGetRCPtr(pSSM, &((PRTRCPTR)pbField)[i]);
+ break;
+ }
+
+ case SSMFIELDTRANS_HCPTR_NI:
+ AssertMsgBreakStmt(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = ssmR3GetHCPtrNI(pSSM, (void **)pbField, fFlags);
+ break;
+
+ case SSMFIELDTRANS_HCPTR_NI_ARRAY:
+ {
+ uint32_t const cEntries = cbField / sizeof(void *);
+ AssertMsgBreakStmt(cbField == cEntries * sizeof(void *) && cEntries, ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = VINF_SUCCESS;
+ for (uint32_t i = 0; i < cEntries && RT_SUCCESS(rc); i++)
+ rc = ssmR3GetHCPtrNI(pSSM, &((void **)pbField)[i], fFlags);
+ break;
+ }
+
+ case SSMFIELDTRANS_HCPTR_HACK_U32:
+ AssertMsgBreakStmt(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ *(uintptr_t *)pbField = 0;
+ rc = tstDevSsmR3DataRead(pSSM, pbField, sizeof(uint32_t));
+ if ((fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE) && ssmR3GetHostBits(pSSM) == 64)
+ {
+ uint32_t u32;
+ rc = tstDevSsmR3DataRead(pSSM, &u32, sizeof(uint32_t));
+ AssertMsgBreakStmt(RT_FAILURE(rc) || u32 == 0 || (fFlags & SSMSTRUCT_FLAGS_SAVED_AS_MEM),
+ ("high=%#x low=%#x (%s)\n", u32, *(uint32_t *)pbField, pCur->pszName),
+ rc = VERR_SSM_FIELD_INVALID_VALUE);
+ }
+ break;
+
+ case SSMFIELDTRANS_U32_ZX_U64:
+ AssertMsgBreakStmt(cbField == sizeof(uint64_t), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ ((uint32_t *)pbField)[1] = 0;
+ rc = pdmR3DevHlp_SSMGetU32(pSSM, (uint32_t *)pbField);
+ break;
+
+
+ case SSMFIELDTRANS_IGNORE:
+ if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
+ rc = pdmR3DevHlp_SSMSkip(pSSM, cbField);
+ break;
+
+ case SSMFIELDTRANS_IGN_GCPHYS:
+ AssertMsgBreakStmt(cbField == sizeof(RTGCPHYS), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
+ rc = pdmR3DevHlp_SSMSkip(pSSM, sizeof(RTGCPHYS));
+ break;
+
+ case SSMFIELDTRANS_IGN_GCPTR:
+ AssertMsgBreakStmt(cbField == sizeof(RTGCPTR), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
+ rc = pdmR3DevHlp_SSMSkip(pSSM, sizeof(RTGCPTR));
+ break;
+
+ case SSMFIELDTRANS_IGN_RCPTR:
+ AssertMsgBreakStmt(cbField == sizeof(RTRCPTR), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
+ rc = pdmR3DevHlp_SSMSkip(pSSM, sizeof(RTRCPTR));
+ break;
+
+ case SSMFIELDTRANS_IGN_HCPTR:
+ AssertMsgBreakStmt(cbField == sizeof(void *), ("%#x (%s)\n", cbField, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
+ rc = pdmR3DevHlp_SSMSkip(pSSM, ssmR3GetHostBits(pSSM) / 8);
+ break;
+
+
+ case SSMFIELDTRANS_OLD:
+ AssertMsgBreakStmt(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = pdmR3DevHlp_SSMSkip(pSSM, pCur->cb);
+ break;
+
+ case SSMFIELDTRANS_OLD_GCPHYS:
+ AssertMsgBreakStmt(pCur->cb == sizeof(RTGCPHYS) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = pdmR3DevHlp_SSMSkip(pSSM, sizeof(RTGCPHYS));
+ break;
+
+ case SSMFIELDTRANS_OLD_GCPTR:
+ AssertMsgBreakStmt(pCur->cb == sizeof(RTGCPTR) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = pdmR3DevHlp_SSMSkip(pSSM, sizeof(RTGCPTR));
+ break;
+
+ case SSMFIELDTRANS_OLD_RCPTR:
+ AssertMsgBreakStmt(pCur->cb == sizeof(RTRCPTR) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = pdmR3DevHlp_SSMSkip(pSSM, sizeof(RTRCPTR));
+ break;
+
+ case SSMFIELDTRANS_OLD_HCPTR:
+ AssertMsgBreakStmt(pCur->cb == sizeof(void *) && pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = pdmR3DevHlp_SSMSkip(pSSM, ssmR3GetHostBits(pSSM) / 8);
+ break;
+
+ case SSMFIELDTRANS_OLD_PAD_HC:
+ AssertMsgBreakStmt(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ rc = pdmR3DevHlp_SSMSkip(pSSM, ssmR3GetHostBits(pSSM) == 64 ? RT_HIWORD(pCur->cb) : RT_LOWORD(pCur->cb));
+ break;
+
+ case SSMFIELDTRANS_OLD_PAD_MSC32:
+ AssertMsgBreakStmt(pCur->off == UINT32_MAX / 2, ("%#x %#x (%s)\n", pCur->cb, pCur->off, pCur->pszName), rc = VERR_SSM_FIELD_INVALID_SIZE);
+ if (ssmR3IsHostMsc32(pSSM))
+ rc = pdmR3DevHlp_SSMSkip(pSSM, pCur->cb);
+ break;
+
+
+ case SSMFIELDTRANS_PAD_HC:
+ case SSMFIELDTRANS_PAD_HC32:
+ case SSMFIELDTRANS_PAD_HC64:
+ case SSMFIELDTRANS_PAD_HC_AUTO:
+ case SSMFIELDTRANS_PAD_MSC32_AUTO:
+ {
+ uint32_t cb32 = RT_BYTE1(pCur->cb);
+ uint32_t cb64 = RT_BYTE2(pCur->cb);
+ uint32_t cbCtx = HC_ARCH_BITS == 64
+ || (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
+ ? cb64 : cb32;
+ uint32_t cbSaved = ssmR3GetHostBits(pSSM) == 64
+ || ( (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
+ && !ssmR3IsHostMsc32(pSSM))
+ ? cb64 : cb32;
+ AssertMsgBreakStmt( cbField == cbCtx
+ && ( ( pCur->off == UINT32_MAX / 2
+ && ( cbField == 0
+ || (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_HC_AUTO
+ || (uintptr_t)pCur->pfnGetPutOrTransformer == SSMFIELDTRANS_PAD_MSC32_AUTO
+ )
+ )
+ || (pCur->off != UINT32_MAX / 2 && cbField != 0)
+ )
+ , ("cbField=%#x cb32=%#x cb64=%#x HC_ARCH_BITS=%u cbCtx=%#x cbSaved=%#x off=%#x\n",
+ cbField, cb32, cb64, HC_ARCH_BITS, cbCtx, cbSaved, pCur->off),
+ rc = VERR_SSM_FIELD_INVALID_PADDING_SIZE);
+ if (fFlags & SSMSTRUCT_FLAGS_DONT_IGNORE)
+ rc = pdmR3DevHlp_SSMSkip(pSSM, cbSaved);
+ break;
+ }
+
+ default:
+ AssertBreakStmt(pCur->pfnGetPutOrTransformer, rc = VERR_SSM_FIELD_INVALID_CALLBACK);
+ rc = pCur->pfnGetPutOrTransformer(pSSM, pCur, pvStruct, fFlags, true /*fGetOrPut*/, pvUser);
+ break;
+ }
+ if (RT_FAILURE(rc))
+ break;
+ }
+
+ off = offField + cbField;
+ }
+
+ if (RT_SUCCESS(rc))
+ AssertMsgStmt( !(fFlags & SSMSTRUCT_FLAGS_FULL_STRUCT)
+ || off == cbStruct,
+ ("off=%#x cbStruct=%#x\n", off, cbStruct),
+ rc = VERR_SSM_FIELD_NOT_CONSECUTIVE);
+
+ if (RT_FAILURE(rc))
+ {
+ if (RT_SUCCESS(pSSM->rc))
+ pSSM->rc = rc;
+ return rc;
+ }
+
+ /*
+ * End marker
+ */
+ if (!(fFlags & (SSMSTRUCT_FLAGS_NO_MARKERS | SSMSTRUCT_FLAGS_NO_TAIL_MARKER)))
+ {
+ rc = pdmR3DevHlp_SSMGetU32(pSSM, &u32Magic);
+ if (RT_FAILURE(rc))
+ return rc;
+ AssertMsgReturn(u32Magic == SSMR3STRUCT_END, ("u32Magic=%#RX32\n", u32Magic), pSSM->rc = VERR_SSM_STRUCTURE_MAGIC);
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMSkipToEndOfUnit(PSSMHANDLE pSSM)
+{
+ RT_NOREF(pSSM);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMSetLoadError(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(6, 7)
+{
+ RT_NOREF(pSSM, rc, RT_SRC_POS_ARGS, pszFormat);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMSetLoadErrorV(PSSMHANDLE pSSM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(6, 0)
+{
+ RT_NOREF(pSSM, rc, RT_SRC_POS_ARGS, pszFormat, va);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMSetCfgError(PSSMHANDLE pSSM, RT_SRC_POS_DECL, const char *pszFormat, ...) RT_IPRT_FORMAT_ATTR(5, 6)
+{
+ RT_NOREF(pSSM, RT_SRC_POS_ARGS, pszFormat);
+ pSSM->rc = VERR_SSM_LOAD_CONFIG_MISMATCH;
+ return pSSM->rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMSetCfgErrorV(PSSMHANDLE pSSM, RT_SRC_POS_DECL, const char *pszFormat, va_list va) RT_IPRT_FORMAT_ATTR(5, 0)
+{
+ RT_NOREF(pSSM, RT_SRC_POS_ARGS, pszFormat, va);
+ pSSM->rc = VERR_SSM_LOAD_CONFIG_MISMATCH;
+ return pSSM->rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_SSMHandleGetStatus(PSSMHANDLE pSSM)
+{
+ RT_NOREF(pSSM);
+ return pSSM->rc;
+}
+
+
+static DECLCALLBACK(SSMAFTER) pdmR3DevHlp_SSMHandleGetAfter(PSSMHANDLE pSSM)
+{
+ RT_NOREF(pSSM);
+ AssertFailed();
+ return SSMAFTER_INVALID;
+}
+
+
+static DECLCALLBACK(bool) pdmR3DevHlp_SSMHandleIsLiveSave(PSSMHANDLE pSSM)
+{
+ RT_NOREF(pSSM);
+ AssertFailed();
+ return false;
+}
+
+
+static DECLCALLBACK(uint32_t) pdmR3DevHlp_SSMHandleMaxDowntime(PSSMHANDLE pSSM)
+{
+ RT_NOREF(pSSM);
+ AssertFailed();
+ return 0;
+}
+
+
+static DECLCALLBACK(uint32_t) pdmR3DevHlp_SSMHandleHostBits(PSSMHANDLE pSSM)
+{
+ RT_NOREF(pSSM);
+ AssertFailed();
+ return 0;
+}
+
+
+static DECLCALLBACK(uint32_t) pdmR3DevHlp_SSMHandleRevision(PSSMHANDLE pSSM)
+{
+ RT_NOREF(pSSM);
+ AssertFailed();
+ return 0;
+}
+
+
+static DECLCALLBACK(uint32_t) pdmR3DevHlp_SSMHandleVersion(PSSMHANDLE pSSM)
+{
+ RT_NOREF(pSSM);
+ AssertFailed();
+ return 0;
+}
+
+
+static DECLCALLBACK(const char *) pdmR3DevHlp_SSMHandleHostOSAndArch(PSSMHANDLE pSSM)
+{
+ RT_NOREF(pSSM);
+ AssertFailed();
+ return NULL;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerCreate} */
+static DECLCALLBACK(int) pdmR3DevHlp_TimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback,
+ void *pvUser, uint32_t fFlags, const char *pszDesc, PTMTIMERHANDLE phTimer)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_TimerCreate: caller='%s'/%d: enmClock=%d pfnCallback=%p pvUser=%p fFlags=%#x pszDesc=%p:{%s} phTimer=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, enmClock, pfnCallback, pvUser, fFlags, pszDesc, pszDesc, phTimer));
+
+ int rc = VINF_SUCCESS;
+ PTMTIMERR3 pTimer = (PTMTIMERR3)RTMemAllocZ(sizeof(TMTIMER));
+ if (RT_LIKELY(pTimer))
+ {
+ pTimer->enmClock = enmClock;
+ pTimer->pfnCallbackDev = pfnCallback;
+ pTimer->pvUser = pvUser;
+ pTimer->fFlags = fFlags;
+ RTListAppend(&pDevIns->Internal.s.pDut->LstTimers, &pTimer->NdDevTimers);
+ *phTimer = (TMTIMERHANDLE)pTimer;
+ }
+ else
+ rc = VERR_NO_MEMORY;
+
+ LogFlow(("pdmR3DevHlp_TimerCreate: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerFromMicro} */
+static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerFromMicro(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicroSecs)
+{
+ RT_NOREF(pDevIns, hTimer, cMicroSecs);
+ AssertFailed();
+ return 0;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerFromMilli} */
+static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerFromMilli(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliSecs)
+{
+ RT_NOREF(pDevIns, hTimer, cMilliSecs);
+ AssertFailed();
+ return 0;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerFromNano} */
+static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerFromNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanoSecs)
+{
+ RT_NOREF(pDevIns, hTimer, cNanoSecs);
+ AssertFailed();
+ return 0;
+}
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerGet} */
+static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerGet(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ RT_NOREF(pDevIns, hTimer);
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ AssertFailed();
+ return 0;
+#else
+ static uint64_t cCnt = 0;
+ return cCnt++;
+#endif
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerGetFreq} */
+static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerGetFreq(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ PTMTIMERR3 pTimer = (PTMTIMERR3)hTimer;
+ switch (pTimer->enmClock)
+ {
+ case TMCLOCK_VIRTUAL:
+ case TMCLOCK_VIRTUAL_SYNC:
+ return TMCLOCK_FREQ_VIRTUAL;
+
+ case TMCLOCK_REAL:
+ return TMCLOCK_FREQ_REAL;
+
+ default:
+ AssertMsgFailed(("Invalid enmClock=%d\n", pTimer->enmClock));
+ return 0;
+ }
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerGetNano} */
+static DECLCALLBACK(uint64_t) pdmR3DevHlp_TimerGetNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ RT_NOREF(pDevIns, hTimer);
+ AssertFailed();
+ return 0;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerIsActive} */
+static DECLCALLBACK(bool) pdmR3DevHlp_TimerIsActive(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ RT_NOREF(pDevIns, hTimer);
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ AssertFailed();
+ return false;
+#else
+ return true;
+#endif
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerIsLockOwner} */
+static DECLCALLBACK(bool) pdmR3DevHlp_TimerIsLockOwner(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ RT_NOREF(pDevIns, hTimer);
+ AssertFailed();
+ return false;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerLockClock} */
+static DECLCALLBACK(VBOXSTRICTRC) pdmR3DevHlp_TimerLockClock(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, int rcBusy)
+{
+ RT_NOREF(pDevIns, hTimer, rcBusy);
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerLockClock2} */
+static DECLCALLBACK(VBOXSTRICTRC) pdmR3DevHlp_TimerLockClock2(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer,
+ PPDMCRITSECT pCritSect, int rcBusy)
+{
+ RT_NOREF(pDevIns, hTimer, pCritSect, rcBusy);
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSet} */
+static DECLCALLBACK(int) pdmR3DevHlp_TimerSet(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t uExpire)
+{
+ RT_NOREF(pDevIns, hTimer, uExpire);
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetFrequencyHint} */
+static DECLCALLBACK(int) pdmR3DevHlp_TimerSetFrequencyHint(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint32_t uHz)
+{
+ RT_NOREF(pDevIns, hTimer, uHz);
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetMicro} */
+static DECLCALLBACK(int) pdmR3DevHlp_TimerSetMicro(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicrosToNext)
+{
+ RT_NOREF(pDevIns, hTimer, cMicrosToNext);
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetMillies} */
+static DECLCALLBACK(int) pdmR3DevHlp_TimerSetMillies(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliesToNext)
+{
+ RT_NOREF(pDevIns, hTimer, cMilliesToNext);
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetNano} */
+static DECLCALLBACK(int) pdmR3DevHlp_TimerSetNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanosToNext)
+{
+ RT_NOREF(pDevIns, hTimer, cNanosToNext);
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetRelative} */
+static DECLCALLBACK(int) pdmR3DevHlp_TimerSetRelative(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cTicksToNext, uint64_t *pu64Now)
+{
+ RT_NOREF(pDevIns, hTimer, cTicksToNext, pu64Now);
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerStop} */
+static DECLCALLBACK(int) pdmR3DevHlp_TimerStop(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ RT_NOREF(pDevIns, hTimer);
+
+#if 1 /** @todo */
+ int rc = VINF_SUCCESS;
+#else
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#endif
+
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerUnlockClock} */
+static DECLCALLBACK(void) pdmR3DevHlp_TimerUnlockClock(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ RT_NOREF(pDevIns, hTimer);
+ AssertFailed();
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerUnlockClock2} */
+static DECLCALLBACK(void) pdmR3DevHlp_TimerUnlockClock2(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect)
+{
+ RT_NOREF(pDevIns, hTimer, pCritSect);
+ AssertFailed();
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSetCritSect} */
+static DECLCALLBACK(int) pdmR3DevHlp_TimerSetCritSect(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ PTMTIMERR3 pTimer = (PTMTIMERR3)hTimer;
+ pTimer->pCritSect = pCritSect;
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerSave} */
+static DECLCALLBACK(int) pdmR3DevHlp_TimerSave(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM)
+{
+ RT_NOREF(pDevIns, hTimer, pSSM);
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerLoad} */
+static DECLCALLBACK(int) pdmR3DevHlp_TimerLoad(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PSSMHANDLE pSSM)
+{
+ RT_NOREF(pDevIns, hTimer);
+
+/** @name Saved state values (comes directly from TM.cpp)
+ * @{ */
+#define TMTIMERSTATE_SAVED_PENDING_STOP 4
+#define TMTIMERSTATE_SAVED_PENDING_SCHEDULE 7
+/** @} */
+
+ /*
+ * Load the state and validate it.
+ */
+ uint8_t u8State;
+ int rc = pdmR3DevHlp_SSMGetU8(pSSM, &u8State);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /* TMTIMERSTATE_SAVED_XXX: Workaround for accidental state shift in r47786 (2009-05-26 19:12:12). */
+ if ( u8State == TMTIMERSTATE_SAVED_PENDING_STOP + 1
+ || u8State == TMTIMERSTATE_SAVED_PENDING_SCHEDULE + 1)
+ u8State--;
+
+ if ( u8State != TMTIMERSTATE_SAVED_PENDING_STOP
+ && u8State != TMTIMERSTATE_SAVED_PENDING_SCHEDULE)
+ {
+ /*AssertLogRelMsgFailed(("u8State=%d\n", u8State));*/
+ return VERR_TM_LOAD_STATE;
+ }
+
+ if (u8State == TMTIMERSTATE_SAVED_PENDING_SCHEDULE)
+ {
+ /*
+ * Load the expire time.
+ */
+ uint64_t u64Expire;
+ rc = pdmR3DevHlp_SSMGetU64(pSSM, &u64Expire);
+ if (RT_FAILURE(rc))
+ return rc;
+
+ /*
+ * Set it.
+ */
+ Log(("u8State=%d u64Expire=%llu\n", u8State, u64Expire));
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTimerDestroy} */
+static DECLCALLBACK(int) pdmR3DevHlp_TimerDestroy(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ RT_NOREF(pDevIns, hTimer);
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_TimerSkipLoad(PSSMHANDLE pSSM, bool *pfActive)
+{
+ RT_NOREF(pSSM, pfActive);
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTMUtcNow} */
+static DECLCALLBACK(PRTTIMESPEC) pdmR3DevHlp_TMUtcNow(PPDMDEVINS pDevIns, PRTTIMESPEC pTime)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_TMUtcNow: caller='%s'/%d: pTime=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pTime));
+
+ RT_NOREF(pDevIns, pTime);
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_TMUtcNow: caller='%s'/%d: returns %RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, RTTimeSpecGetNano(pTime)));
+ return pTime;
+}
+
+
+static DECLCALLBACK(bool) pdmR3DevHlp_CFGMExists(PCFGMNODE pNode, const char *pszName)
+{
+ RT_NOREF(pNode, pszName);
+ AssertFailed();
+ return false;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryType(PCFGMNODE pNode, const char *pszName, PCFGMVALUETYPE penmType)
+{
+ RT_NOREF(pNode, pszName, penmType);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQuerySize(PCFGMNODE pNode, const char *pszName, size_t *pcb)
+{
+ if (!pNode)
+ return VERR_CFGM_NO_PARENT;
+
+ PCTSTDEVCFGITEM pCfgItem;
+ int rc = tstDev_CfgmR3ResolveItem(pNode->pDut->pTest->paCfgItems, pNode->pDut->pTest->cCfgItems, pszName, &pCfgItem);
+ if (RT_SUCCESS(rc))
+ {
+ switch (pCfgItem->enmType)
+ {
+ case TSTDEVCFGITEMTYPE_INTEGER:
+ *pcb = sizeof(uint64_t);
+ break;
+
+ case TSTDEVCFGITEMTYPE_STRING:
+ *pcb = strlen(pCfgItem->u.psz) + 1;
+ break;
+
+ case TSTDEVCFGITEMTYPE_BYTES:
+ AssertFailed();
+ break;
+
+ default:
+ rc = VERR_CFGM_IPE_1;
+ AssertMsgFailed(("Invalid value type %d\n", pCfgItem->enmType));
+ break;
+ }
+ }
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryInteger(PCFGMNODE pNode, const char *pszName, uint64_t *pu64)
+{
+ if (!pNode)
+ return VERR_CFGM_NO_PARENT;
+
+ PCTSTDEVCFGITEM pCfgItem;
+ int rc = tstDev_CfgmR3ResolveItem(pNode->pDut->pTest->paCfgItems, pNode->pDut->pTest->cCfgItems, pszName, &pCfgItem);
+ if (RT_SUCCESS(rc))
+ {
+ if (pCfgItem->enmType == TSTDEVCFGITEMTYPE_INTEGER)
+ *pu64 = (uint64_t)pCfgItem->u.i64;
+ else
+ rc = VERR_CFGM_NOT_INTEGER;
+ }
+
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryIntegerDef(PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def)
+{
+ int rc = pdmR3DevHlp_CFGMQueryInteger(pNode, pszName, pu64);
+ if (RT_FAILURE(rc))
+ {
+ *pu64 = u64Def;
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
+ rc = VINF_SUCCESS;
+ }
+
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryString(PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString)
+{
+ if (!pNode)
+ return VERR_CFGM_NO_PARENT;
+
+ PCTSTDEVCFGITEM pCfgItem;
+ int rc = tstDev_CfgmR3ResolveItem(pNode->pDut->pTest->paCfgItems, pNode->pDut->pTest->cCfgItems, pszName, &pCfgItem);
+ if (RT_SUCCESS(rc))
+ {
+ switch (pCfgItem->enmType)
+ {
+ case TSTDEVCFGITEMTYPE_STRING:
+ {
+ size_t cchVal = strlen(pCfgItem->u.psz);
+ if (cchString <= cchVal + 1)
+ memcpy(pszString, pCfgItem->u.psz, cchVal);
+ else
+ rc = VERR_CFGM_NOT_ENOUGH_SPACE;
+ break;
+ }
+ case TSTDEVCFGITEMTYPE_INTEGER:
+ case TSTDEVCFGITEMTYPE_BYTES:
+ default:
+ rc = VERR_CFGM_IPE_1;
+ AssertMsgFailed(("Invalid value type %d\n", pCfgItem->enmType));
+ break;
+ }
+ }
+ else
+ rc = VERR_CFGM_VALUE_NOT_FOUND;
+
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryStringDef(PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString, const char *pszDef)
+{
+ int rc = pdmR3DevHlp_CFGMQueryString(pNode, pszName, pszString, cchString);
+ if (RT_FAILURE(rc) && rc != VERR_CFGM_NOT_ENOUGH_SPACE)
+ {
+ size_t cchDef = strlen(pszDef);
+ if (cchString > cchDef)
+ {
+ memcpy(pszString, pszDef, cchDef);
+ memset(pszString + cchDef, 0, cchString - cchDef);
+ if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
+ rc = VINF_SUCCESS;
+ }
+ else if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_NO_PARENT)
+ rc = VERR_CFGM_NOT_ENOUGH_SPACE;
+ }
+
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryPassword(PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString)
+{
+ return pdmR3DevHlp_CFGMQueryString(pNode, pszName, pszString, cchString);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryPasswordDef(PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString, const char *pszDef)
+{
+ return pdmR3DevHlp_CFGMQueryStringDef(pNode, pszName, pszString, cchString, pszDef);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryBytes(PCFGMNODE pNode, const char *pszName, void *pvData, size_t cbData)
+{
+ RT_NOREF(pNode, pszName, pvData, cbData);
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+#else
+ memset(pvData, 0, cbData);
+ return VINF_SUCCESS;
+#endif
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryU64(PCFGMNODE pNode, const char *pszName, uint64_t *pu64)
+{
+ return pdmR3DevHlp_CFGMQueryInteger(pNode, pszName, pu64);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryU64Def(PCFGMNODE pNode, const char *pszName, uint64_t *pu64, uint64_t u64Def)
+{
+ return pdmR3DevHlp_CFGMQueryIntegerDef(pNode, pszName, pu64, u64Def);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryS64(PCFGMNODE pNode, const char *pszName, int64_t *pi64)
+{
+ RT_NOREF(pNode, pszName, pi64);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryS64Def(PCFGMNODE pNode, const char *pszName, int64_t *pi64, int64_t i64Def)
+{
+ RT_NOREF(pNode, pszName, pi64, i64Def);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryU32(PCFGMNODE pNode, const char *pszName, uint32_t *pu32)
+{
+ uint64_t u64;
+ int rc = pdmR3DevHlp_CFGMQueryInteger(pNode, pszName, &u64);
+ if (RT_SUCCESS(rc))
+ {
+ if (!(u64 & UINT64_C(0xffffffff00000000)))
+ *pu32 = (uint32_t)u64;
+ else
+ rc = VERR_CFGM_INTEGER_TOO_BIG;
+ }
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryU32Def(PCFGMNODE pNode, const char *pszName, uint32_t *pu32, uint32_t u32Def)
+{
+ uint64_t u64;
+ int rc = pdmR3DevHlp_CFGMQueryIntegerDef(pNode, pszName, &u64, u32Def);
+ if (RT_SUCCESS(rc))
+ {
+ if (!(u64 & UINT64_C(0xffffffff00000000)))
+ *pu32 = (uint32_t)u64;
+ else
+ rc = VERR_CFGM_INTEGER_TOO_BIG;
+ }
+ if (RT_FAILURE(rc))
+ *pu32 = u32Def;
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryS32(PCFGMNODE pNode, const char *pszName, int32_t *pi32)
+{
+ uint64_t u64;
+ int rc = pdmR3DevHlp_CFGMQueryInteger(pNode, pszName, &u64);
+ if (RT_SUCCESS(rc))
+ {
+ if ( !(u64 & UINT64_C(0xffffffff80000000))
+ || (u64 & UINT64_C(0xffffffff80000000)) == UINT64_C(0xffffffff80000000))
+ *pi32 = (int32_t)u64;
+ else
+ rc = VERR_CFGM_INTEGER_TOO_BIG;
+ }
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryS32Def(PCFGMNODE pNode, const char *pszName, int32_t *pi32, int32_t i32Def)
+{
+ uint64_t u64;
+ int rc = pdmR3DevHlp_CFGMQueryIntegerDef(pNode, pszName, &u64, i32Def);
+ if (RT_SUCCESS(rc))
+ {
+ if ( !(u64 & UINT64_C(0xffffffff80000000))
+ || (u64 & UINT64_C(0xffffffff80000000)) == UINT64_C(0xffffffff80000000))
+ *pi32 = (int32_t)u64;
+ else
+ rc = VERR_CFGM_INTEGER_TOO_BIG;
+ }
+ if (RT_FAILURE(rc))
+ *pi32 = i32Def;
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryU16(PCFGMNODE pNode, const char *pszName, uint16_t *pu16)
+{
+ uint64_t u64;
+ int rc = pdmR3DevHlp_CFGMQueryInteger(pNode, pszName, &u64);
+ if (RT_SUCCESS(rc))
+ {
+ if (!(u64 & UINT64_C(0xffffffffffff0000)))
+ *pu16 = (int16_t)u64;
+ else
+ rc = VERR_CFGM_INTEGER_TOO_BIG;
+ }
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryU16Def(PCFGMNODE pNode, const char *pszName, uint16_t *pu16, uint16_t u16Def)
+{
+ uint64_t u64;
+ int rc = pdmR3DevHlp_CFGMQueryIntegerDef(pNode, pszName, &u64, u16Def);
+ if (RT_SUCCESS(rc))
+ {
+ if (!(u64 & UINT64_C(0xffffffffffff0000)))
+ *pu16 = (int16_t)u64;
+ else
+ rc = VERR_CFGM_INTEGER_TOO_BIG;
+ }
+ if (RT_FAILURE(rc))
+ *pu16 = u16Def;
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryS16(PCFGMNODE pNode, const char *pszName, int16_t *pi16)
+{
+ RT_NOREF(pNode, pszName, pi16);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryS16Def(PCFGMNODE pNode, const char *pszName, int16_t *pi16, int16_t i16Def)
+{
+ RT_NOREF(pNode, pszName, pi16, i16Def);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryU8(PCFGMNODE pNode, const char *pszName, uint8_t *pu8)
+{
+ uint64_t u64;
+ int rc = pdmR3DevHlp_CFGMQueryInteger(pNode, pszName, &u64);
+ if (RT_SUCCESS(rc))
+ {
+ if (!(u64 & UINT64_C(0xffffffffffffff00)))
+ *pu8 = (uint8_t)u64;
+ else
+ rc = VERR_CFGM_INTEGER_TOO_BIG;
+ }
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryU8Def(PCFGMNODE pNode, const char *pszName, uint8_t *pu8, uint8_t u8Def)
+{
+ uint64_t u64;
+ int rc = pdmR3DevHlp_CFGMQueryIntegerDef(pNode, pszName, &u64, u8Def);
+ if (RT_SUCCESS(rc))
+ {
+ if (!(u64 & UINT64_C(0xffffffffffffff00)))
+ *pu8 = (uint8_t)u64;
+ else
+ rc = VERR_CFGM_INTEGER_TOO_BIG;
+ }
+ if (RT_FAILURE(rc))
+ *pu8 = u8Def;
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryS8(PCFGMNODE pNode, const char *pszName, int8_t *pi8)
+{
+ RT_NOREF(pNode, pszName, pi8);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryS8Def(PCFGMNODE pNode, const char *pszName, int8_t *pi8, int8_t i8Def)
+{
+ RT_NOREF(pNode, pszName, pi8, i8Def);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryBool(PCFGMNODE pNode, const char *pszName, bool *pf)
+{
+ uint64_t u64;
+ int rc = pdmR3DevHlp_CFGMQueryInteger(pNode, pszName, &u64);
+ if (RT_SUCCESS(rc))
+ *pf = u64 ? true : false;
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryBoolDef(PCFGMNODE pNode, const char *pszName, bool *pf, bool fDef)
+{
+ uint64_t u64;
+ int rc = pdmR3DevHlp_CFGMQueryIntegerDef(pNode, pszName, &u64, fDef);
+ *pf = u64 ? true : false;
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryPort(PCFGMNODE pNode, const char *pszName, PRTIOPORT pPort)
+{
+ RT_NOREF(pNode, pszName, pPort);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryPortDef(PCFGMNODE pNode, const char *pszName, PRTIOPORT pPort, RTIOPORT PortDef)
+{
+ AssertCompileSize(RTIOPORT, 2);
+ return pdmR3DevHlp_CFGMQueryU16Def(pNode, pszName, pPort, PortDef);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryUInt(PCFGMNODE pNode, const char *pszName, unsigned int *pu)
+{
+ RT_NOREF(pNode, pszName, pu);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryUIntDef(PCFGMNODE pNode, const char *pszName, unsigned int *pu, unsigned int uDef)
+{
+ RT_NOREF(pNode, pszName, pu, uDef);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQuerySInt(PCFGMNODE pNode, const char *pszName, signed int *pi)
+{
+ RT_NOREF(pNode, pszName, pi);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQuerySIntDef(PCFGMNODE pNode, const char *pszName, signed int *pi, signed int iDef)
+{
+ RT_NOREF(pNode, pszName, pi, iDef);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryPtr(PCFGMNODE pNode, const char *pszName, void **ppv)
+{
+ uint64_t u64;
+ int rc = pdmR3DevHlp_CFGMQueryInteger(pNode, pszName, &u64);
+ if (RT_SUCCESS(rc))
+ {
+ uintptr_t u = (uintptr_t)u64;
+ if (u64 == u)
+ *ppv = (void *)u;
+ else
+ rc = VERR_CFGM_INTEGER_TOO_BIG;
+ }
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryPtrDef(PCFGMNODE pNode, const char *pszName, void **ppv, void *pvDef)
+{
+ RT_NOREF(pNode, pszName, ppv, pvDef);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryGCPtr(PCFGMNODE pNode, const char *pszName, PRTGCPTR pGCPtr)
+{
+ RT_NOREF(pNode, pszName, pGCPtr);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryGCPtrDef(PCFGMNODE pNode, const char *pszName, PRTGCPTR pGCPtr, RTGCPTR GCPtrDef)
+{
+ RT_NOREF(pNode, pszName, pGCPtr, GCPtrDef);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryGCPtrU(PCFGMNODE pNode, const char *pszName, PRTGCUINTPTR pGCPtr)
+{
+ RT_NOREF(pNode, pszName, pGCPtr);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryGCPtrUDef(PCFGMNODE pNode, const char *pszName, PRTGCUINTPTR pGCPtr, RTGCUINTPTR GCPtrDef)
+{
+ RT_NOREF(pNode, pszName, pGCPtr, GCPtrDef);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryGCPtrS(PCFGMNODE pNode, const char *pszName, PRTGCINTPTR pGCPtr)
+{
+ RT_NOREF(pNode, pszName, pGCPtr);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryGCPtrSDef(PCFGMNODE pNode, const char *pszName, PRTGCINTPTR pGCPtr, RTGCINTPTR GCPtrDef)
+{
+ RT_NOREF(pNode, pszName, pGCPtr, GCPtrDef);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryStringAlloc(PCFGMNODE pNode, const char *pszName, char **ppszString)
+{
+ if (!pNode)
+ return VERR_CFGM_NO_PARENT;
+
+ PCTSTDEVCFGITEM pCfgItem;
+ int rc = tstDev_CfgmR3ResolveItem(pNode->pDut->pTest->paCfgItems, pNode->pDut->pTest->cCfgItems, pszName, &pCfgItem);
+ if (RT_SUCCESS(rc))
+ {
+ switch (pCfgItem->enmType)
+ {
+ case TSTDEVCFGITEMTYPE_STRING:
+ {
+ *ppszString = (char *)RTMemDup(pCfgItem->u.psz, strlen(pCfgItem->u.psz) + 1);
+ if (RT_LIKELY(*ppszString))
+ rc = VINF_SUCCESS;
+ else
+ rc = VERR_NO_STR_MEMORY;
+ break;
+ }
+ case TSTDEVCFGITEMTYPE_INTEGER:
+ case TSTDEVCFGITEMTYPE_BYTES:
+ default:
+ rc = VERR_CFGM_IPE_1;
+ AssertMsgFailed(("Invalid value type %d\n", pCfgItem->enmType));
+ break;
+ }
+ }
+ else
+ rc = VERR_CFGM_VALUE_NOT_FOUND;
+
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMQueryStringAllocDef(PCFGMNODE pNode, const char *pszName, char **ppszString, const char *pszDef)
+{
+ if (!pNode)
+ return VERR_CFGM_NO_PARENT;
+
+ PCTSTDEVCFGITEM pCfgItem;
+ int rc = tstDev_CfgmR3ResolveItem(pNode->pDut->pTest->paCfgItems, pNode->pDut->pTest->cCfgItems, pszName, &pCfgItem);
+ if (RT_SUCCESS(rc))
+ {
+ switch (pCfgItem->enmType)
+ {
+ case TSTDEVCFGITEMTYPE_STRING:
+ {
+ *ppszString = (char *)RTMemDup(pCfgItem->u.psz, strlen(pCfgItem->u.psz) + 1);
+ if (RT_LIKELY(*ppszString))
+ rc = VINF_SUCCESS;
+ else
+ rc = VERR_NO_STR_MEMORY;
+ break;
+ }
+ case TSTDEVCFGITEMTYPE_INTEGER:
+ case TSTDEVCFGITEMTYPE_BYTES:
+ default:
+ rc = VERR_CFGM_IPE_1;
+ AssertMsgFailed(("Invalid value type %d\n", pCfgItem->enmType));
+ break;
+ }
+ }
+ else
+ {
+ if (pszDef)
+ {
+ *ppszString = (char *)RTMemDup(pszDef, strlen(pszDef) + 1);
+ if (RT_LIKELY(*ppszString))
+ rc = VINF_SUCCESS;
+ else
+ rc = VERR_NO_STR_MEMORY;
+ }
+ else
+ {
+ *ppszString = NULL;
+ rc = VINF_SUCCESS;
+ }
+ }
+
+ return rc;
+}
+
+
+static DECLCALLBACK(PCFGMNODE) pdmR3DevHlp_CFGMGetParent(PCFGMNODE pNode)
+{
+ RT_NOREF(pNode);
+ AssertFailed();
+ return NULL;
+}
+
+
+static DECLCALLBACK(PCFGMNODE) pdmR3DevHlp_CFGMGetChild(PCFGMNODE pNode, const char *pszPath)
+{
+ RT_NOREF(pNode, pszPath);
+ AssertFailed();
+ return NULL;
+}
+
+
+static DECLCALLBACK(PCFGMNODE) pdmR3DevHlp_CFGMGetChildF(PCFGMNODE pNode, const char *pszPathFormat, ...) RT_IPRT_FORMAT_ATTR(2, 3)
+{
+ RT_NOREF(pNode, pszPathFormat);
+ AssertFailed();
+ return NULL;
+}
+
+
+static DECLCALLBACK(PCFGMNODE) pdmR3DevHlp_CFGMGetChildFV(PCFGMNODE pNode, const char *pszPathFormat, va_list Args) RT_IPRT_FORMAT_ATTR(3, 0)
+{
+ RT_NOREF(pNode, pszPathFormat, Args);
+ AssertFailed();
+ return NULL;
+}
+
+
+static DECLCALLBACK(PCFGMNODE) pdmR3DevHlp_CFGMGetFirstChild(PCFGMNODE pNode)
+{
+ RT_NOREF(pNode);
+ AssertFailed();
+ return NULL;
+}
+
+
+static DECLCALLBACK(PCFGMNODE) pdmR3DevHlp_CFGMGetNextChild(PCFGMNODE pCur)
+{
+ RT_NOREF(pCur);
+ AssertFailed();
+ return NULL;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMGetName(PCFGMNODE pCur, char *pszName, size_t cchName)
+{
+ RT_NOREF(pCur, pszName, cchName);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(size_t) pdmR3DevHlp_CFGMGetNameLen(PCFGMNODE pCur)
+{
+ RT_NOREF(pCur);
+ AssertFailed();
+ return 0;
+}
+
+
+static DECLCALLBACK(bool) pdmR3DevHlp_CFGMAreChildrenValid(PCFGMNODE pNode, const char *pszzValid)
+{
+ RT_NOREF(pNode, pszzValid);
+ AssertFailed();
+ return false;
+}
+
+
+static DECLCALLBACK(PCFGMLEAF) pdmR3DevHlp_CFGMGetFirstValue(PCFGMNODE pCur)
+{
+ RT_NOREF(pCur);
+ AssertFailed();
+ return NULL;
+}
+
+
+static DECLCALLBACK(PCFGMLEAF) pdmR3DevHlp_CFGMGetNextValue(PCFGMLEAF pCur)
+{
+ RT_NOREF(pCur);
+ AssertFailed();
+ return NULL;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMGetValueName(PCFGMLEAF pCur, char *pszName, size_t cchName)
+{
+ RT_NOREF(pCur, pszName, cchName);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(size_t) pdmR3DevHlp_CFGMGetValueNameLen(PCFGMLEAF pCur)
+{
+ RT_NOREF(pCur);
+ AssertFailed();
+ return 0;
+}
+
+
+static DECLCALLBACK(CFGMVALUETYPE) pdmR3DevHlp_CFGMGetValueType(PCFGMLEAF pCur)
+{
+ RT_NOREF(pCur);
+ AssertFailed();
+ return CFGMVALUETYPE_INTEGER;
+}
+
+
+static DECLCALLBACK(bool) pdmR3DevHlp_CFGMAreValuesValid(PCFGMNODE pNode, const char *pszzValid)
+{
+ if (pNode && pNode->pDut->pTest->paCfgItems)
+ {
+ PCTSTDEVCFGITEM pDevCfgItem = pNode->pDut->pTest->paCfgItems;
+ for (uint32_t i = 0; i < pNode->pDut->pTest->cCfgItems; i++)
+ {
+ size_t cchKey = strlen(pDevCfgItem->pszKey);
+
+ /* search pszzValid for the name */
+ const char *psz = pszzValid;
+ while (*psz)
+ {
+ size_t cch = strlen(psz);
+ if ( cch == cchKey
+ && !memcmp(psz, pDevCfgItem->pszKey, cch))
+ break;
+
+ /* next */
+ psz += cch + 1;
+ }
+
+ /* if at end of pszzValid we didn't find it => failure */
+ if (!*psz)
+ return false;
+
+ pDevCfgItem++;
+ }
+ }
+
+ return true;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_CFGMValidateConfig(PCFGMNODE pNode, const char *pszNode,
+ const char *pszValidValues, const char *pszValidNodes,
+ const char *pszWho, uint32_t uInstance)
+{
+ RT_NOREF(pNode, pszNode, pszValidValues, pszValidNodes, pszWho, uInstance);
+#if 1
+ return VINF_SUCCESS;
+#else
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+#endif
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTMTimeVirtGet} */
+static DECLCALLBACK(uint64_t) pdmR3DevHlp_TMTimeVirtGet(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_TMTimeVirtGet: caller='%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+
+ uint64_t u64Time = 0;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_TMTimeVirtGet: caller='%s'/%d: returns %RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, u64Time));
+ return u64Time;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTMTimeVirtGetFreq} */
+static DECLCALLBACK(uint64_t) pdmR3DevHlp_TMTimeVirtGetFreq(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_TMTimeVirtGetFreq: caller='%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+
+ uint64_t u64Freq = 0;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_TMTimeVirtGetFreq: caller='%s'/%d: returns %RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, u64Freq));
+ return u64Freq;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTMTimeVirtGetNano} */
+static DECLCALLBACK(uint64_t) pdmR3DevHlp_TMTimeVirtGetNano(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_TMTimeVirtGetNano: caller='%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+
+ uint64_t u64Nano = RTTimeNanoTS();
+
+ LogFlow(("pdmR3DevHlp_TMTimeVirtGetNano: caller='%s'/%d: returns %RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, u64Nano));
+ return u64Nano;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTMCpuTicksPerSecond} */
+static DECLCALLBACK(uint64_t) pdmR3DevHlp_TMCpuTicksPerSecond(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_TMCpuTicksPerSecond: caller='%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+
+ AssertFailed();
+ uint64_t u64CpuTicksPerSec = 0;
+
+ LogFlow(("pdmR3DevHlp_TMCpuTicksPerSecond: caller='%s'/%d: returns %RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, u64CpuTicksPerSec));
+ return u64CpuTicksPerSec;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnGetSupDrvSession} */
+static DECLCALLBACK(PSUPDRVSESSION) pdmR3DevHlp_GetSupDrvSession(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_GetSupDrvSession: caller='%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+
+ PSUPDRVSESSION pSession = NIL_RTR0PTR;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_GetSupDrvSession: caller='%s'/%d: returns %#p\n", pDevIns->pReg->szName, pDevIns->iInstance, pSession));
+ return pSession;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnQueryGenericUserObject} */
+static DECLCALLBACK(void *) pdmR3DevHlp_QueryGenericUserObject(PPDMDEVINS pDevIns, PCRTUUID pUuid)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_QueryGenericUserObject: caller='%s'/%d: pUuid=%p:%RTuuid\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pUuid, pUuid));
+
+#if defined(DEBUG_bird) || defined(DEBUG_ramshankar) || defined(DEBUG_sunlover) || defined(DEBUG_michael) || defined(DEBUG_andy)
+ AssertMsgFailed(("'%s' wants %RTuuid - external only interface!\n", pDevIns->pReg->szName, pUuid));
+#endif
+
+ void *pvRet = NULL;
+ AssertFailed();
+
+ LogRel(("pdmR3DevHlp_QueryGenericUserObject: caller='%s'/%d: returns %#p for %RTuuid\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pvRet, pUuid));
+ return pvRet;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPGMHandlerPhysicalTypeRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_PGMHandlerPhysicalTypeRegister(PPDMDEVINS pDevIns, PGMPHYSHANDLERKIND enmKind,
+ R3PTRTYPE(PFNPGMPHYSHANDLER) pfnHandlerR3,
+ const char *pszHandlerR0, const char *pszPfHandlerR0,
+ const char *pszHandlerRC, const char *pszPfHandlerRC,
+ const char *pszDesc, PPGMPHYSHANDLERTYPE phType)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(enmKind, pfnHandlerR3, pszHandlerR0, pszPfHandlerR0, pszHandlerRC, pszPfHandlerRC, pszDesc, phType);
+ LogFlow(("pdmR3DevHlp_PGMHandlerPhysicalTypeRegister: caller='%s'/%d: enmKind=%d pfnHandlerR3=%p pszHandlerR0=%p:{%s} pszPfHandlerR0=%p:{%s} pszHandlerRC=%p:{%s} pszPfHandlerRC=%p:{%s} pszDesc=%p:{%s} phType=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pfnHandlerR3,
+ pszHandlerR0, pszHandlerR0, pszPfHandlerR0, pszPfHandlerR0,
+ pszHandlerRC, pszHandlerRC, pszPfHandlerRC, pszPfHandlerRC,
+ pszDesc, pszDesc, phType));
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogRel(("pdmR3DevHlp_PGMHandlerPhysicalTypeRegister: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPhysRead} */
+static DECLCALLBACK(int) pdmR3DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PhysRead: caller='%s'/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x fFlags=%#x\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvBuf, cbRead, fFlags));
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ VBOXSTRICTRC rcStrict = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ RTRandBytes(pvBuf, cbRead);
+ VBOXSTRICTRC rcStrict = VINF_SUCCESS;
+#endif
+
+ Log(("pdmR3DevHlp_PhysRead: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
+ return VBOXSTRICTRC_VAL(rcStrict);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPhysWrite} */
+static DECLCALLBACK(int) pdmR3DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: GCPhys=%RGp pvBuf=%p cbWrite=%#xfFlags=%#x\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvBuf, cbWrite, fFlags));
+
+ VBOXSTRICTRC rcStrict = VERR_NOT_IMPLEMENTED;;
+ AssertFailed();
+
+ Log(("pdmR3DevHlp_PhysWrite: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
+ return VBOXSTRICTRC_VAL(rcStrict);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPhysGCPhys2CCPtr} */
+static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPhys2CCPtr(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t fFlags, void **ppv, PPGMPAGEMAPLOCK pLock)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PhysGCPhys2CCPtr: caller='%s'/%d: GCPhys=%RGp fFlags=%#x ppv=%p pLock=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, fFlags, ppv, pLock));
+ AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
+
+ int rc = VERR_NOT_IMPLEMENTED;;
+ AssertFailed();
+
+ Log(("pdmR3DevHlp_PhysGCPhys2CCPtr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPhysGCPhys2CCPtrReadOnly} */
+static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, uint32_t fFlags, const void **ppv, PPGMPAGEMAPLOCK pLock)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly: caller='%s'/%d: GCPhys=%RGp fFlags=%#x ppv=%p pLock=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, fFlags, ppv, pLock));
+ AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
+
+ int rc = VERR_NOT_IMPLEMENTED;;
+ AssertFailed();
+
+ Log(("pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPhysReleasePageMappingLock} */
+static DECLCALLBACK(void) pdmR3DevHlp_PhysReleasePageMappingLock(PPDMDEVINS pDevIns, PPGMPAGEMAPLOCK pLock)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PhysReleasePageMappingLock: caller='%s'/%d: pLock=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pLock));
+
+ AssertFailed();
+
+ Log(("pdmR3DevHlp_PhysReleasePageMappingLock: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPhysBulkGCPhys2CCPtr} */
+static DECLCALLBACK(int) pdmR3DevHlp_PhysBulkGCPhys2CCPtr(PPDMDEVINS pDevIns, uint32_t cPages, PCRTGCPHYS paGCPhysPages,
+ uint32_t fFlags, void **papvPages, PPGMPAGEMAPLOCK paLocks)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PhysBulkGCPhys2CCPtr: caller='%s'/%d: cPages=%#x paGCPhysPages=%p (%RGp,..) fFlags=%#x papvPages=%p paLocks=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, cPages, paGCPhysPages, paGCPhysPages[0], fFlags, papvPages, paLocks));
+ AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
+ AssertReturn(cPages > 0, VERR_INVALID_PARAMETER);
+
+ int rc = VERR_NOT_IMPLEMENTED;;
+ AssertFailed();
+
+ Log(("pdmR3DevHlp_PhysBulkGCPhys2CCPtr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPhysBulkGCPhys2CCPtrReadOnly} */
+static DECLCALLBACK(int) pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly(PPDMDEVINS pDevIns, uint32_t cPages, PCRTGCPHYS paGCPhysPages,
+ uint32_t fFlags, const void **papvPages, PPGMPAGEMAPLOCK paLocks)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly: caller='%s'/%d: cPages=%#x paGCPhysPages=%p (%RGp,...) fFlags=%#x papvPages=%p paLocks=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, cPages, paGCPhysPages, paGCPhysPages[0], fFlags, papvPages, paLocks));
+ AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
+ AssertReturn(cPages > 0, VERR_INVALID_PARAMETER);
+
+ int rc = VERR_NOT_IMPLEMENTED;;
+ AssertFailed();
+
+ Log(("pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPhysBulkReleasePageMappingLocks} */
+static DECLCALLBACK(void) pdmR3DevHlp_PhysBulkReleasePageMappingLocks(PPDMDEVINS pDevIns, uint32_t cPages, PPGMPAGEMAPLOCK paLocks)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PhysBulkReleasePageMappingLocks: caller='%s'/%d: cPages=%#x paLocks=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, cPages, paLocks));
+ Assert(cPages > 0);
+
+ AssertFailed();
+
+ Log(("pdmR3DevHlp_PhysBulkReleasePageMappingLocks: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPhysIsGCPhysNormal} */
+static DECLCALLBACK(bool) pdmR3DevHlp_PhysIsGCPhysNormal(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PhysIsGCPhysNormal: caller='%s'/%d: GCPhys=%RGp\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, GCPhys));
+
+ bool fNormal = true;
+ AssertFailed();
+
+ Log(("pdmR3DevHlp_PhysIsGCPhysNormal: caller='%s'/%d: returns %RTbool\n", pDevIns->pReg->szName, pDevIns->iInstance, fNormal));
+ return fNormal;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPhysChangeMemBalloon} */
+static DECLCALLBACK(int) pdmR3DevHlp_PhysChangeMemBalloon(PPDMDEVINS pDevIns, bool fInflate, unsigned cPages, RTGCPHYS *paPhysPage)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PhysChangeMemBalloon: caller='%s'/%d: fInflate=%RTbool cPages=%u paPhysPage=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, fInflate, cPages, paPhysPage));
+
+ int rc = VERR_NOT_IMPLEMENTED;;
+ AssertFailed();
+
+ Log(("pdmR3DevHlp_PhysChangeMemBalloon: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCpuGetGuestMicroarch} */
+static DECLCALLBACK(CPUMMICROARCH) pdmR3DevHlp_CpuGetGuestMicroarch(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_CpuGetGuestMicroarch: caller='%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+
+ CPUMMICROARCH enmMicroarch = kCpumMicroarch_Intel_P6;
+
+ Log(("pdmR3DevHlp_CpuGetGuestMicroarch: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, enmMicroarch));
+ return enmMicroarch;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCpuGetGuestAddrWidths} */
+static DECLCALLBACK(void) pdmR3DevHlp_CpuGetGuestAddrWidths(PPDMDEVINS pDevIns, uint8_t *pcPhysAddrWidth,
+ uint8_t *pcLinearAddrWidth)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_CpuGetGuestAddrWidths: caller='%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance));
+ AssertPtrReturnVoid(pcPhysAddrWidth);
+ AssertPtrReturnVoid(pcLinearAddrWidth);
+
+ AssertFailed();
+
+ Log(("pdmR3DevHlp_CpuGetGuestAddrWidths: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCpuGetGuestScalableBusFrequency} */
+static DECLCALLBACK(uint64_t) pdmR3DevHlp_CpuGetGuestScalableBusFrequency(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_CpuGetGuestScalableBusFrequency: caller='%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+
+ AssertFailed();
+ uint64_t u64Fsb = 0;
+
+ Log(("pdmR3DevHlp_CpuGetGuestScalableBusFrequency: caller='%s'/%d: returns %#RX64\n", pDevIns->pReg->szName, pDevIns->iInstance, u64Fsb));
+ return u64Fsb;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPhysReadGCVirt} */
+static DECLCALLBACK(int) pdmR3DevHlp_PhysReadGCVirt(PPDMDEVINS pDevIns, void *pvDst, RTGCPTR GCVirtSrc, size_t cb)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: pvDst=%p GCVirt=%RGv cb=%#x\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pvDst, GCVirtSrc, cb));
+
+ int rc = VERR_NOT_IMPLEMENTED;;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_PhysReadGCVirt: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPhysWriteGCVirt} */
+static DECLCALLBACK(int) pdmR3DevHlp_PhysWriteGCVirt(PPDMDEVINS pDevIns, RTGCPTR GCVirtDst, const void *pvSrc, size_t cb)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: GCVirtDst=%RGv pvSrc=%p cb=%#x\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, GCVirtDst, pvSrc, cb));
+
+ int rc = VERR_NOT_IMPLEMENTED;;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_PhysWriteGCVirt: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPhysGCPtr2GCPhys} */
+static DECLCALLBACK(int) pdmR3DevHlp_PhysGCPtr2GCPhys(PPDMDEVINS pDevIns, RTGCPTR GCPtr, PRTGCPHYS pGCPhys)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: GCPtr=%RGv pGCPhys=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, GCPtr, pGCPhys));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: returns %Rrc *pGCPhys=%RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *pGCPhys));
+
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMMHeapAlloc} */
+static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAlloc(PPDMDEVINS pDevIns, size_t cb)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: cb=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, cb));
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ void *pv = NULL;
+ AssertFailed();
+#else
+ void *pv = RTMemAlloc(cb);
+#endif
+
+ LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pv));
+ return pv;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMMHeapAllocZ} */
+static DECLCALLBACK(void *) pdmR3DevHlp_MMHeapAllocZ(PPDMDEVINS pDevIns, size_t cb)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: cb=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, cb));
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ void *pv = NULL;
+ AssertFailed();
+#else
+ void *pv = RTMemAllocZ(cb);
+#endif
+
+ LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pv));
+ return pv;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMMHeapAPrintfV} */
+static DECLCALLBACK(char *) pdmR3DevHlp_MMHeapAPrintfV(PPDMDEVINS pDevIns, MMTAG enmTag, const char *pszFormat, va_list va)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_MMHeapAPrintfV: caller='%s'/%d: enmTag=%u pszFormat=%p:{%s}\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, enmTag, pszFormat, pszFormat));
+
+ RT_NOREF(va);
+ AssertFailed();
+ char *psz = NULL;
+
+ LogFlow(("pdmR3DevHlp_MMHeapAPrintfV: caller='%s'/%d: returns %p:{%s}\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, psz, psz));
+ return psz;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMMHeapFree} */
+static DECLCALLBACK(void) pdmR3DevHlp_MMHeapFree(PPDMDEVINS pDevIns, void *pv)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
+ LogFlow(("pdmR3DevHlp_MMHeapFree: caller='%s'/%d: pv=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pv));
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ PTSTDEVMMHEAPALLOC pHeapAlloc = (PTSTDEVMMHEAPALLOC)((uint8_t *)pv - RT_UOFFSETOF(TSTDEVMMHEAPALLOC, abAlloc[0]));
+ PTSTDEVDUTINT pThis = pHeapAlloc->pDut;
+
+ tstDevDutLockExcl(pThis);
+ RTListNodeRemove(&pHeapAlloc->NdMmHeap);
+ tstDevDutUnlockExcl(pThis);
+
+ /* Poison */
+ memset(&pHeapAlloc->abAlloc[0], 0xfc, pHeapAlloc->cbAlloc);
+ RTMemFree(pHeapAlloc);
+#else
+ RTMemFree(pv);
+#endif
+
+ LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMMPhysGetRamSize} */
+static DECLCALLBACK(uint64_t) pdmR3DevHlp_MMPhysGetRamSize(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
+ LogFlow(("pdmR3DevHlp_MMPhysGetRamSize: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ AssertFailed();
+ uint64_t cb = 0;
+#else
+ uint64_t cb = _4G;
+#endif
+
+ LogFlow(("pdmR3DevHlp_MMPhysGetRamSize: caller='%s'/%d: returns %RU64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, cb));
+ return cb;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMMPhysGetRamSizeBelow4GB} */
+static DECLCALLBACK(uint32_t) pdmR3DevHlp_MMPhysGetRamSizeBelow4GB(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
+ LogFlow(("pdmR3DevHlp_MMPhysGetRamSizeBelow4GB: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
+
+ AssertFailed();
+ uint32_t cb = 0;
+
+ LogFlow(("pdmR3DevHlp_MMPhysGetRamSizeBelow4GB: caller='%s'/%d: returns %RU32\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, cb));
+ return cb;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnMMPhysGetRamSizeAbove4GB} */
+static DECLCALLBACK(uint64_t) pdmR3DevHlp_MMPhysGetRamSizeAbove4GB(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
+ LogFlow(("pdmR3DevHlp_MMPhysGetRamSizeAbove4GB: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
+
+ AssertFailed();
+ uint64_t cb = 0;
+
+ LogFlow(("pdmR3DevHlp_MMPhysGetRamSizeAbove4GB: caller='%s'/%d: returns %RU64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, cb));
+ return cb;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMState} */
+static DECLCALLBACK(VMSTATE) pdmR3DevHlp_VMState(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ VMSTATE enmVMState = VMSTATE_CREATING;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_VMState: caller='%s'/%d: returns %d\n", pDevIns->pReg->szName, pDevIns->iInstance,
+ enmVMState));
+ return enmVMState;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMTeleportedAndNotFullyResumedYet} */
+static DECLCALLBACK(bool) pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ bool fRc = false;
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ AssertFailed();
+#endif
+
+ LogFlow(("pdmR3DevHlp_VMState: caller='%s'/%d: returns %RTbool\n", pDevIns->pReg->szName, pDevIns->iInstance,
+ fRc));
+ return fRc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMSetErrorV} */
+static DECLCALLBACK(int) pdmR3DevHlp_VMSetErrorV(PPDMDEVINS pDevIns, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ RT_NOREF(pDevIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
+ AssertFailed();
+
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMSetRuntimeErrorV} */
+static DECLCALLBACK(int) pdmR3DevHlp_VMSetRuntimeErrorV(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszErrorId, const char *pszFormat, va_list va)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ RT_NOREF(pDevIns, fFlags, pszErrorId, pszFormat, va);
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMWaitForDeviceReady} */
+static DECLCALLBACK(int) pdmR3DevHlp_VMWaitForDeviceReady(PPDMDEVINS pDevIns, VMCPUID idCpu)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_VMWaitForDeviceReady: caller='%s'/%d: idCpu=%u\n", pDevIns->pReg->szName, pDevIns->iInstance, idCpu));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_VMWaitForDeviceReady: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMNotifyCpuDeviceReady} */
+static DECLCALLBACK(int) pdmR3DevHlp_VMNotifyCpuDeviceReady(PPDMDEVINS pDevIns, VMCPUID idCpu)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_VMNotifyCpuDeviceReady: caller='%s'/%d: idCpu=%u\n", pDevIns->pReg->szName, pDevIns->iInstance, idCpu));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_VMNotifyCpuDeviceReady: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMReqCallNoWaitV} */
+static DECLCALLBACK(int) pdmR3DevHlp_VMReqCallNoWaitV(PPDMDEVINS pDevIns, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, va_list Args)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_VMReqCallNoWaitV: caller='%s'/%d: idDstCpu=%u pfnFunction=%p cArgs=%u\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, idDstCpu, pfnFunction, cArgs));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed(); RT_NOREF(Args);
+
+ LogFlow(("pdmR3DevHlp_VMReqCallNoWaitV: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMReqPriorityCallWaitV} */
+static DECLCALLBACK(int) pdmR3DevHlp_VMReqPriorityCallWaitV(PPDMDEVINS pDevIns, VMCPUID idDstCpu, PFNRT pfnFunction, unsigned cArgs, va_list Args)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_VMReqCallNoWaitV: caller='%s'/%d: idDstCpu=%u pfnFunction=%p cArgs=%u\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, idDstCpu, pfnFunction, cArgs));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed(); RT_NOREF(Args);
+
+ LogFlow(("pdmR3DevHlp_VMReqCallNoWaitV: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFStopV} */
+static DECLCALLBACK(int) pdmR3DevHlp_DBGFStopV(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction, const char *pszFormat, va_list args)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+#ifdef LOG_ENABLED
+ va_list va2;
+ va_copy(va2, args);
+ LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: pszFile=%p:{%s} iLine=%d pszFunction=%p:{%s} pszFormat=%p:{%s} (%N)\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pszFile, pszFile, iLine, pszFunction, pszFunction, pszFormat, pszFormat, pszFormat, &va2));
+ va_end(va2);
+#endif
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_DBGFStopV: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFInfoRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_DBGFInfoRegister(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFHANDLERDEV pfnHandler)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pszName, pszName, pszDesc, pszDesc, pfnHandler));
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+
+ LogFlow(("pdmR3DevHlp_DBGFInfoRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFInfoRegisterArgv} */
+static DECLCALLBACK(int) pdmR3DevHlp_DBGFInfoRegisterArgv(PPDMDEVINS pDevIns, const char *pszName, const char *pszDesc, PFNDBGFINFOARGVDEV pfnHandler)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DBGFInfoRegisterArgv: caller='%s'/%d: pszName=%p:{%s} pszDesc=%p:{%s} pfnHandler=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pszName, pszName, pszDesc, pszDesc, pfnHandler));
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_DBGFInfoRegisterArgv: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFRegRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_DBGFRegRegister(PPDMDEVINS pDevIns, PCDBGFREGDESC paRegisters)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DBGFRegRegister: caller='%s'/%d: paRegisters=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, paRegisters));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_DBGFRegRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFTraceBuf} */
+static DECLCALLBACK(RTTRACEBUF) pdmR3DevHlp_DBGFTraceBuf(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RTTRACEBUF hTraceBuf = NIL_RTTRACEBUF;
+ AssertFailed();
+ LogFlow(("pdmR3DevHlp_DBGFTraceBuf: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, hTraceBuf));
+ return hTraceBuf;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFReportBugCheck} */
+static DECLCALLBACK(VBOXSTRICTRC) pdmR3DevHlp_DBGFReportBugCheck(PPDMDEVINS pDevIns, DBGFEVENTTYPE enmEvent, uint64_t uBugCheck,
+ uint64_t uP1, uint64_t uP2, uint64_t uP3, uint64_t uP4)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DBGFReportBugCheck: caller='%s'/%d: enmEvent=%u uBugCheck=%#x uP1=%#x uP2=%#x uP3=%#x uP4=%#x\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, enmEvent, uBugCheck, uP1, uP2, uP3, uP4));
+
+ AssertFailed();
+ VBOXSTRICTRC rcStrict = VERR_NOT_IMPLEMENTED;
+
+ LogFlow(("pdmR3DevHlp_DBGFReportBugCheck: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict)));
+ return rcStrict;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFCoreWrite} */
+static DECLCALLBACK(int) pdmR3DevHlp_DBGFCoreWrite(PPDMDEVINS pDevIns, const char *pszFilename, bool fReplaceFile)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DBGFCoreWrite: caller='%s'/%d: pszFilename=%p:{%s} fReplaceFile=%RTbool\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pszFilename, pszFilename, fReplaceFile));
+
+ AssertFailed();
+ int rc = VERR_NOT_IMPLEMENTED;
+
+ LogFlow(("pdmR3DevHlp_DBGFCoreWrite: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFInfoLogHlp} */
+static DECLCALLBACK(PCDBGFINFOHLP) pdmR3DevHlp_DBGFInfoLogHlp(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF(pDevIns);
+ LogFlow(("pdmR3DevHlp_DBGFInfoLogHlp: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
+
+ AssertFailed();
+ PCDBGFINFOHLP pHlp = NULL;
+
+ LogFlow(("pdmR3DevHlp_DBGFInfoLogHlp: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pHlp));
+ return pHlp;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFRegNmQueryU64} */
+static DECLCALLBACK(int) pdmR3DevHlp_DBGFRegNmQueryU64(PPDMDEVINS pDevIns, VMCPUID idDefCpu, const char *pszReg, uint64_t *pu64)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DBGFRegNmQueryU64: caller='%s'/%d: idDefCpu=%u pszReg=%p:{%s} pu64=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, idDefCpu, pszReg, pszReg, pu64));
+
+ AssertFailed();
+ int rc = VERR_NOT_IMPLEMENTED;
+
+ LogFlow(("pdmR3DevHlp_DBGFRegNmQueryU64: caller='%s'/%d: returns %Rrc *pu64=%#RX64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc, *pu64));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDBGFRegPrintfV} */
+static DECLCALLBACK(int) pdmR3DevHlp_DBGFRegPrintfV(PPDMDEVINS pDevIns, VMCPUID idCpu, char *pszBuf, size_t cbBuf,
+ const char *pszFormat, va_list va)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DBGFRegPrintfV: caller='%s'/%d: idCpu=%u pszBuf=%p cbBuf=%u pszFormat=%p:{%s}\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, idCpu, pszBuf, cbBuf, pszFormat, pszFormat));
+
+ AssertFailed();
+ RT_NOREF(va);
+ int rc = VERR_NOT_IMPLEMENTED;
+
+ LogFlow(("pdmR3DevHlp_DBGFRegPrintfV: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSTAMRegister} */
+static DECLCALLBACK(void) pdmR3DevHlp_STAMRegister(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, const char *pszName,
+ STAMUNIT enmUnit, const char *pszDesc)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ RT_NOREF(pDevIns, pvSample, enmType, pszName, enmUnit, pszDesc);
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ AssertFailed();
+#endif
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSTAMRegisterV} */
+static DECLCALLBACK(void) pdmR3DevHlp_STAMRegisterV(PPDMDEVINS pDevIns, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
+ STAMUNIT enmUnit, const char *pszDesc, const char *pszName, va_list args)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ RT_NOREF(pDevIns, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ AssertFailed();
+#endif
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVHLPR3,pfnPCIRegister}
+ */
+static DECLCALLBACK(int) pdmR3DevHlp_PCIRegister(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t fFlags,
+ uint8_t uPciDevNo, uint8_t uPciFunNo, const char *pszName)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: pPciDev=%p:{.config={%#.256Rhxs} fFlags=%#x uPciDevNo=%#x uPciFunNo=%#x pszName=%p:{%s}\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->abConfig, fFlags, uPciDevNo, uPciFunNo, pszName, pszName ? pszName : ""));
+
+ /*
+ * Validate input.
+ */
+ AssertLogRelMsgReturn(pDevIns->pReg->cMaxPciDevices > 0,
+ ("'%s'/%d: cMaxPciDevices is 0\n", pDevIns->pReg->szName, pDevIns->iInstance),
+ VERR_WRONG_ORDER);
+ AssertLogRelMsgReturn(RT_VALID_PTR(pPciDev),
+ ("'%s'/%d: Invalid pPciDev value: %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pPciDev),
+ VERR_INVALID_POINTER);
+ AssertLogRelMsgReturn(PDMPciDevGetVendorId(pPciDev),
+ ("'%s'/%d: Vendor ID is not set!\n", pDevIns->pReg->szName, pDevIns->iInstance),
+ VERR_INVALID_POINTER);
+ AssertLogRelMsgReturn( uPciDevNo < 32
+ || uPciDevNo == PDMPCIDEVREG_DEV_NO_FIRST_UNUSED
+ || uPciDevNo == PDMPCIDEVREG_DEV_NO_SAME_AS_PREV,
+ ("'%s'/%d: Invalid PCI device number: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, uPciDevNo),
+ VERR_INVALID_PARAMETER);
+ AssertLogRelMsgReturn( uPciFunNo < 8
+ || uPciFunNo == PDMPCIDEVREG_FUN_NO_FIRST_UNUSED,
+ ("'%s'/%d: Invalid PCI funcion number: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, uPciFunNo),
+ VERR_INVALID_PARAMETER);
+ AssertLogRelMsgReturn(!(fFlags & ~PDMPCIDEVREG_F_VALID_MASK),
+ ("'%s'/%d: Invalid flags: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, fFlags),
+ VERR_INVALID_FLAGS);
+ if (!pszName)
+ pszName = pDevIns->pReg->szName;
+
+#if 0
+ AssertLogRelReturn(RT_VALID_PTR(pszName), VERR_INVALID_POINTER);
+ AssertLogRelReturn(!pPciDev->Int.s.fRegistered, VERR_PDM_NOT_PCI_DEVICE);
+ AssertLogRelReturn(pPciDev == PDMDEV_GET_PPCIDEV(pDevIns, pPciDev->Int.s.idxSubDev), VERR_PDM_NOT_PCI_DEVICE);
+ AssertLogRelReturn(pPciDev == PDMDEV_CALC_PPCIDEV(pDevIns, pPciDev->Int.s.idxSubDev), VERR_PDM_NOT_PCI_DEVICE);
+ AssertMsgReturn(pPciDev->u32Magic == PDMPCIDEV_MAGIC, ("%#x\n", pPciDev->u32Magic), VERR_PDM_NOT_PCI_DEVICE);
+#endif
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPCIRegisterMsi} */
+static DECLCALLBACK(int) pdmR3DevHlp_PCIRegisterMsi(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, PPDMMSIREG pMsiReg)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ if (!pPciDev) /* NULL is an alias for the default PCI device. */
+ pPciDev = pDevIns->apPciDevs[0];
+ AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
+ LogFlow(("pdmR3DevHlp_PCIRegisterMsi: caller='%s'/%d: pPciDev=%p:{%#x} pMsgReg=%p:{cMsiVectors=%d, cMsixVectors=%d}\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, pMsiReg, pMsiReg->cMsiVectors, pMsiReg->cMsixVectors));
+ PDMPCIDEV_ASSERT_VALID_RET(pDevIns, pPciDev);
+
+ AssertLogRelMsgReturn(pDevIns->pReg->cMaxPciDevices > 0,
+ ("'%s'/%d: cMaxPciDevices is 0\n", pDevIns->pReg->szName, pDevIns->iInstance),
+ VERR_WRONG_ORDER);
+ AssertLogRelMsgReturn(pMsiReg->cMsixVectors <= pDevIns->pReg->cMaxMsixVectors,
+ ("'%s'/%d: cMsixVectors=%u cMaxMsixVectors=%u\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pMsiReg->cMsixVectors, pDevIns->pReg->cMaxMsixVectors),
+ VERR_INVALID_FLAGS);
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+
+ LogFlow(("pdmR3DevHlp_PCIRegisterMsi: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPCIIORegionRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_PCIIORegionRegister(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
+ RTGCPHYS cbRegion, PCIADDRESSSPACE enmType, uint32_t fFlags,
+ uint64_t hHandle, PFNPCIIOREGIONMAP pfnMapUnmap)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ if (!pPciDev) /* NULL is an alias for the default PCI device. */
+ pPciDev = pDevIns->apPciDevs[0];
+ AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
+ LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: pPciDev=%p:{%#x} iRegion=%d cbRegion=%RGp enmType=%d fFlags=%#x, hHandle=%#RX64 pfnMapUnmap=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iRegion, cbRegion, enmType, fFlags, hHandle, pfnMapUnmap));
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ PDMPCIDEV_ASSERT_VALID_RET(pDevIns, pPciDev);
+#endif
+
+ /*
+ * Validate input.
+ */
+ if (iRegion >= VBOX_PCI_NUM_REGIONS)
+ {
+ Assert(iRegion < VBOX_PCI_NUM_REGIONS);
+ LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc (iRegion)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ switch ((int)enmType)
+ {
+ case PCI_ADDRESS_SPACE_IO:
+ /*
+ * Sanity check: don't allow to register more than 32K of the PCI I/O space.
+ */
+ AssertLogRelMsgReturn(cbRegion <= _32K,
+ ("caller='%s'/%d: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, cbRegion),
+ VERR_INVALID_PARAMETER);
+ break;
+
+ case PCI_ADDRESS_SPACE_MEM:
+ case PCI_ADDRESS_SPACE_MEM_PREFETCH:
+ /*
+ * Sanity check: Don't allow to register more than 2GB of the PCI MMIO space.
+ */
+ AssertLogRelMsgReturn(cbRegion <= MM_MMIO_32_MAX,
+ ("caller='%s'/%d: %RGp (max %RGp)\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, (RTGCPHYS)MM_MMIO_32_MAX),
+ VERR_OUT_OF_RANGE);
+ break;
+
+ case PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM:
+ case PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_MEM_PREFETCH:
+ /*
+ * Sanity check: Don't allow to register more than 64GB of the 64-bit PCI MMIO space.
+ */
+ AssertLogRelMsgReturn(cbRegion <= MM_MMIO_64_MAX,
+ ("caller='%s'/%d: %RGp (max %RGp)\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, cbRegion, MM_MMIO_64_MAX),
+ VERR_OUT_OF_RANGE);
+ break;
+
+ default:
+ AssertMsgFailed(("enmType=%#x is unknown\n", enmType));
+ LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc (enmType)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ AssertMsgReturn( pfnMapUnmap
+ || ( hHandle != UINT64_MAX
+ && (fFlags & PDMPCIDEV_IORGN_F_HANDLE_MASK) != PDMPCIDEV_IORGN_F_NO_HANDLE),
+ ("caller='%s'/%d: fFlags=%#x hHandle=%#RX64\n", pDevIns->pReg->szName, pDevIns->iInstance, fFlags, hHandle),
+ VERR_INVALID_PARAMETER);
+
+ AssertMsgReturn(!(fFlags & ~PDMPCIDEV_IORGN_F_VALID_MASK), ("fFlags=%#x\n", fFlags), VERR_INVALID_FLAGS);
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPCIInterceptConfigAccesses} */
+static DECLCALLBACK(int) pdmR3DevHlp_PCIInterceptConfigAccesses(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev,
+ PFNPCICONFIGREAD pfnRead, PFNPCICONFIGWRITE pfnWrite)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ if (!pPciDev) /* NULL is an alias for the default PCI device. */
+ pPciDev = pDevIns->apPciDevs[0];
+ AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
+ LogFlow(("pdmR3DevHlp_PCIInterceptConfigAccesses: caller='%s'/%d: pPciDev=%p pfnRead=%p pfnWrite=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pfnRead, pfnWrite));
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ PDMPCIDEV_ASSERT_VALID_RET(pDevIns, pPciDev);
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_PCIInterceptConfigAccesses: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPCIConfigWrite} */
+static DECLCALLBACK(VBOXSTRICTRC)
+pdmR3DevHlp_PCIConfigWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress, unsigned cb, uint32_t u32Value)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertPtrReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
+ LogFlow(("pdmR3DevHlp_PCIConfigWrite: caller='%s'/%d: pPciDev=%p uAddress=%#x cd=%d u32Value=%#x\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, uAddress, cb, u32Value));
+
+ VBOXSTRICTRC rcStrict = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_PCIConfigWrite: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict)));
+ return rcStrict;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPCIConfigRead} */
+static DECLCALLBACK(VBOXSTRICTRC)
+pdmR3DevHlp_PCIConfigRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t uAddress, unsigned cb, uint32_t *pu32Value)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertPtrReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
+ LogFlow(("pdmR3DevHlp_PCIConfigRead: caller='%s'/%d: pPciDev=%p uAddress=%#x cd=%d pu32Value=%p:{%#x}\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, uAddress, cb, pu32Value, *pu32Value));
+
+ VBOXSTRICTRC rcStrict = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_PCIConfigRead: caller='%s'/%d: returns %Rrc (*pu32Value=%#x)\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict), *pu32Value));
+ return rcStrict;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysRead} */
+static DECLCALLBACK(int)
+pdmR3DevHlp_PCIPhysRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ if (!pPciDev) /* NULL is an alias for the default PCI device. */
+ pPciDev = pDevIns->apPciDevs[0];
+ AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
+ //PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
+
+#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
+ /*
+ * Just check the busmaster setting here and forward the request to the generic read helper.
+ */
+ if (PCIDevIsBusmaster(pPciDev))
+ { /* likely */ }
+ else
+ {
+ Log(("pdmR3DevHlp_PCIPhysRead: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbRead=%#zx\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbRead));
+ memset(pvBuf, 0xff, cbRead);
+ return VERR_PDM_NOT_PCI_BUS_MASTER;
+ }
+#endif
+
+ RT_NOREF(fFlags);
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ RTRandBytes(pvBuf, cbRead);
+ int rc = VINF_SUCCESS;
+#endif
+
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysWrite} */
+static DECLCALLBACK(int)
+pdmR3DevHlp_PCIPhysWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ if (!pPciDev) /* NULL is an alias for the default PCI device. */
+ pPciDev = pDevIns->apPciDevs[0];
+ AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
+ //PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
+
+#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
+ /*
+ * Just check the busmaster setting here and forward the request to the generic read helper.
+ */
+ if (PCIDevIsBusmaster(pPciDev))
+ { /* likely */ }
+ else
+ {
+ Log(("pdmR3DevHlp_PCIPhysWrite: caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbWrite=%#zx\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbWrite));
+ return VERR_PDM_NOT_PCI_BUS_MASTER;
+ }
+#endif
+
+ RT_NOREF(GCPhys, pvBuf, cbWrite, fFlags);
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysGCPhys2CCPtr} */
+static DECLCALLBACK(int) pdmR3DevHlp_PCIPhysGCPhys2CCPtr(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
+ uint32_t fFlags, void **ppv, PPGMPAGEMAPLOCK pLock)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ if (!pPciDev) /* NULL is an alias for the default PCI device. */
+ pPciDev = pDevIns->apPciDevs[0];
+ AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
+ PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
+
+#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
+ if (PCIDevIsBusmaster(pPciDev))
+ { /* likely */ }
+ else
+ {
+ LogFunc(("caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp fFlags=%#RX32\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, fFlags));
+ return VERR_PDM_NOT_PCI_BUS_MASTER;
+ }
+#endif
+
+ AssertFailed(); RT_NOREF(ppv, pLock);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysGCPhys2CCPtrReadOnly} */
+static DECLCALLBACK(int) pdmR3DevHlp_PCIPhysGCPhys2CCPtrReadOnly(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
+ uint32_t fFlags, void const **ppv, PPGMPAGEMAPLOCK pLock)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ if (!pPciDev) /* NULL is an alias for the default PCI device. */
+ pPciDev = pDevIns->apPciDevs[0];
+ AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
+ PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
+
+#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
+ if (PCIDevIsBusmaster(pPciDev))
+ { /* likely */ }
+ else
+ {
+ LogFunc(("caller='%s'/%d: returns %Rrc - Not bus master! GCPhys=%RGp fFlags=%#RX32\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, fFlags));
+ return VERR_PDM_NOT_PCI_BUS_MASTER;
+ }
+#endif
+
+ AssertFailed(); RT_NOREF(ppv, pLock);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysBulkGCPhys2CCPtr} */
+static DECLCALLBACK(int) pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtr(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t cPages,
+ PCRTGCPHYS paGCPhysPages, uint32_t fFlags, void **papvPages,
+ PPGMPAGEMAPLOCK paLocks)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ if (!pPciDev) /* NULL is an alias for the default PCI device. */
+ pPciDev = pDevIns->apPciDevs[0];
+ AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
+ PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
+
+#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
+ if (PCIDevIsBusmaster(pPciDev))
+ { /* likely */ }
+ else
+ {
+ LogFunc(("caller='%s'/%d: returns %Rrc - Not bus master! cPages=%zu fFlags=%#RX32\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, cPages, fFlags));
+ return VERR_PDM_NOT_PCI_BUS_MASTER;
+ }
+#endif
+
+ AssertFailed(); RT_NOREF(paGCPhysPages, fFlags, papvPages, paLocks);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPCIPhysBulkGCPhys2CCPtrReadOnly} */
+static DECLCALLBACK(int) pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtrReadOnly(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t cPages,
+ PCRTGCPHYS paGCPhysPages, uint32_t fFlags,
+ const void **papvPages, PPGMPAGEMAPLOCK paLocks)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ if (!pPciDev) /* NULL is an alias for the default PCI device. */
+ pPciDev = pDevIns->apPciDevs[0];
+ AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
+ PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
+
+#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
+ if (PCIDevIsBusmaster(pPciDev))
+ { /* likely */ }
+ else
+ {
+ LogFunc(("caller='%s'/%d: returns %Rrc - Not bus master! cPages=%zu fFlags=%#RX32\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VERR_PDM_NOT_PCI_BUS_MASTER, cPages, fFlags));
+ return VERR_PDM_NOT_PCI_BUS_MASTER;
+ }
+#endif
+
+ AssertFailed(); RT_NOREF(paGCPhysPages, fFlags, papvPages, paLocks);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrq} */
+static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ if (!pPciDev) /* NULL is an alias for the default PCI device. */
+ pPciDev = pDevIns->apPciDevs[0];
+ AssertReturnVoid(pPciDev);
+ LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: pPciDev=%p:{%#x} iIrq=%d iLevel=%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iIrq, iLevel));
+ //PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ RT_NOREF(iIrq, iLevel);
+ AssertFailed();
+#endif
+
+ LogFlow(("pdmR3DevHlp_PCISetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPCISetIrqNoWait} */
+static DECLCALLBACK(void) pdmR3DevHlp_PCISetIrqNoWait(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
+{
+ pdmR3DevHlp_PCISetIrq(pDevIns, pPciDev, iIrq, iLevel);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrq} */
+static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: iIrq=%d iLevel=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, iIrq, iLevel));
+
+ /*
+ * Validate input.
+ */
+ Assert(iIrq < 16);
+ Assert((uint32_t)iLevel <= PDM_IRQ_LEVEL_FLIP_FLOP);
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ AssertFailed();
+#endif
+
+ LogFlow(("pdmR3DevHlp_ISASetIrq: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnISASetIrqNoWait} */
+static DECLCALLBACK(void) pdmR3DevHlp_ISASetIrqNoWait(PPDMDEVINS pDevIns, int iIrq, int iLevel)
+{
+ pdmR3DevHlp_ISASetIrq(pDevIns, iIrq, iLevel);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDriverAttach} */
+static DECLCALLBACK(int) pdmR3DevHlp_DriverAttach(PPDMDEVINS pDevIns, uint32_t iLun, PPDMIBASE pBaseInterface, PPDMIBASE *ppBaseInterface, const char *pszDesc)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: iLun=%d pBaseInterface=%p ppBaseInterface=%p pszDesc=%p:{%s}\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, iLun, pBaseInterface, ppBaseInterface, pszDesc, pszDesc));
+
+#if 1
+ int rc = VINF_SUCCESS;
+ if (iLun == PDM_STATUS_LUN)
+ *ppBaseInterface = &pDevIns->Internal.s.pDut->IBaseSts;
+ else
+ rc = VERR_PDM_NO_ATTACHED_DRIVER;
+#else
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#endif
+
+ LogFlow(("pdmR3DevHlp_DriverAttach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDriverDetach} */
+static DECLCALLBACK(int) pdmR3DevHlp_DriverDetach(PPDMDEVINS pDevIns, PPDMDRVINS pDrvIns, uint32_t fFlags)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
+ LogFlow(("pdmR3DevHlp_DriverDetach: caller='%s'/%d: pDrvIns=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pDrvIns));
+
+ RT_NOREF(fFlags);
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_DriverDetach: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDriverReconfigure} */
+static DECLCALLBACK(int) pdmR3DevHlp_DriverReconfigure(PPDMDEVINS pDevIns, uint32_t iLun, uint32_t cDepth,
+ const char * const *papszDrivers, PCFGMNODE *papConfigs, uint32_t fFlags)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DriverReconfigure: caller='%s'/%d: iLun=%u cDepth=%u fFlags=%#x\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, iLun, cDepth, fFlags));
+
+ /*
+ * Validate input.
+ */
+ AssertReturn(cDepth <= 8, VERR_INVALID_PARAMETER);
+ AssertPtrReturn(papszDrivers, VERR_INVALID_POINTER);
+ AssertPtrNullReturn(papConfigs, VERR_INVALID_POINTER);
+ for (uint32_t i = 0; i < cDepth; i++)
+ {
+ AssertPtrReturn(papszDrivers[i], VERR_INVALID_POINTER);
+ size_t cchDriver = strlen(papszDrivers[i]);
+ AssertReturn(cchDriver > 0 && cchDriver < RT_SIZEOFMEMB(PDMDRVREG, szName), VERR_OUT_OF_RANGE);
+
+ if (papConfigs)
+ AssertPtrNullReturn(papConfigs[i], VERR_INVALID_POINTER);
+ }
+ AssertReturn(fFlags == 0, VERR_INVALID_FLAGS);
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_DriverReconfigure: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnQueueCreate} */
+static DECLCALLBACK(int) pdmR3DevHlp_QueueCreate(PPDMDEVINS pDevIns, size_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
+ PFNPDMQUEUEDEV pfnCallback, bool fRZEnabled, const char *pszName,
+ PDMQUEUEHANDLE *phQueue)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: cbItem=%#x cItems=%#x cMilliesInterval=%u pfnCallback=%p fRZEnabled=%RTbool pszName=%p:{%s} phQueue=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, cbItem, cItems, cMilliesInterval, pfnCallback, fRZEnabled, pszName, pszName, phQueue));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_QueueCreate: caller='%s'/%d: returns %Rrc *ppQueue=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phQueue));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnQueueAlloc} */
+static DECLCALLBACK(PPDMQUEUEITEMCORE) pdmR3DevHlp_QueueAlloc(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
+{
+ RT_NOREF(pDevIns, hQueue);
+ AssertFailed();
+ return NULL;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnQueueInsert} */
+static DECLCALLBACK(void) pdmR3DevHlp_QueueInsert(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)
+{
+ RT_NOREF(pDevIns, hQueue, pItem);
+ AssertFailed();
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnQueueFlushIfNecessary} */
+static DECLCALLBACK(bool) pdmR3DevHlp_QueueFlushIfNecessary(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
+{
+ RT_NOREF(pDevIns, hQueue);
+ AssertFailed();
+ return false;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTaskCreate} */
+static DECLCALLBACK(int) pdmR3DevHlp_TaskCreate(PPDMDEVINS pDevIns, uint32_t fFlags, const char *pszName,
+ PFNPDMTASKDEV pfnCallback, void *pvUser, PDMTASKHANDLE *phTask)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: pfnCallback=%p fFlags=%#x pszName=%p:{%s} phTask=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pfnCallback, fFlags, pszName, pszName, phTask));
+
+ RT_NOREF(pDevIns, fFlags, pszName, pfnCallback, pvUser, phTask);
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnTaskTrigger} */
+static DECLCALLBACK(int) pdmR3DevHlp_TaskTrigger(PPDMDEVINS pDevIns, PDMTASKHANDLE hTask)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: hTask=%RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, hTask));
+
+ RT_NOREF(pDevIns, hTask);
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_TaskTrigger: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventCreate} */
+static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventCreate(PPDMDEVINS pDevIns, PSUPSEMEVENT phEvent)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SUPSemEventCreate: caller='%s'/%d: phEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, phEvent));
+
+ RTSEMEVENT hEvt;
+ int rc = RTSemEventCreate(&hEvt);
+ if (RT_SUCCESS(rc))
+ *phEvent = (SUPSEMEVENT)hEvt;
+
+ LogFlow(("pdmR3DevHlp_SUPSemEventCreate: caller='%s'/%d: returns %Rrc *phEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phEvent));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventClose} */
+static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventClose(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SUPSemEventClose: caller='%s'/%d: hEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEvent));
+
+ int rc = RTSemEventDestroy((RTSEMEVENT)hEvent);
+
+ LogFlow(("pdmR3DevHlp_SUPSemEventClose: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventSignal} */
+static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventSignal(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SUPSemEventSignal: caller='%s'/%d: hEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEvent));
+
+ int rc = RTSemEventSignal((RTSEMEVENT)hEvent);
+
+ LogFlow(("pdmR3DevHlp_SUPSemEventSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventWaitNoResume} */
+static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint32_t cMillies)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: hEvent=%p cNsTimeout=%RU32\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cMillies));
+
+ int rc = RTSemEventWaitNoResume((RTSEMEVENT)hEvent, cMillies);
+
+ LogFlow(("pdmR3DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventWaitNsAbsIntr} */
+static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t uNsTimeout)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: hEvent=%p uNsTimeout=%RU64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hEvent, uNsTimeout));
+
+ int rc = RTSemEventWait((RTSEMEVENT)hEvent, uNsTimeout / RT_NS_1MS);
+
+ LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventWaitNsRelIntr} */
+static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t cNsTimeout)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: hEvent=%p cNsTimeout=%RU64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cNsTimeout));
+
+ int rc = RTSemEventWait((RTSEMEVENT)hEvent, cNsTimeout / RT_NS_1MS);
+
+ LogFlow(("pdmR3DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventGetResolution} */
+static DECLCALLBACK(uint32_t) pdmR3DevHlp_SUPSemEventGetResolution(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SUPSemEventGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
+
+ RT_NOREF(pDevIns);
+ uint32_t cNsResolution = 0;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_SUPSemEventGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
+ return cNsResolution;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiCreate} */
+static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiCreate(PPDMDEVINS pDevIns, PSUPSEMEVENTMULTI phEventMulti)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiCreate: caller='%s'/%d: phEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, phEventMulti));
+
+ RT_NOREF(pDevIns, phEventMulti);
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiCreate: caller='%s'/%d: returns %Rrc *phEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *phEventMulti));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiClose} */
+static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiClose(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiClose: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
+
+ RT_NOREF(pDevIns, hEventMulti);
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiClose: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiSignal} */
+static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiSignal(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
+
+ RT_NOREF(pDevIns, hEventMulti);
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiReset} */
+static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiReset(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiReset: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
+
+ RT_NOREF(pDevIns, hEventMulti);
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiWaitNoResume} */
+static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
+ uint32_t cMillies)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: hEventMulti=%p cMillies=%RU32\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cMillies));
+
+ RT_NOREF(pDevIns, hEventMulti, cMillies);
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiWaitNsAbsIntr} */
+static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
+ uint64_t uNsTimeout)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: hEventMulti=%p uNsTimeout=%RU64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, uNsTimeout));
+
+ RT_NOREF(pDevIns, hEventMulti, uNsTimeout);
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiWaitNsRelIntr} */
+static DECLCALLBACK(int) pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
+ uint64_t cNsTimeout)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: hEventMulti=%p cNsTimeout=%RU64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cNsTimeout));
+
+ RT_NOREF(pDevIns, hEventMulti, cNsTimeout);
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSUPSemEventMultiGetResolution} */
+static DECLCALLBACK(uint32_t) pdmR3DevHlp_SUPSemEventMultiGetResolution(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
+
+ uint32_t cNsResolution = 0;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
+ return cNsResolution;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectInit} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectInit(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
+ const char *pszNameFmt, va_list va)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszNameFmt=%p:{%s}\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pszNameFmt, pszNameFmt));
+
+ RT_NOREF(RT_SRC_POS_ARGS, pszNameFmt, va);
+ int rc = RTCritSectInit(&pCritSect->s.CritSect);
+
+ LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetNop} */
+static DECLCALLBACK(PPDMCRITSECT) pdmR3DevHlp_CritSectGetNop(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ PPDMCRITSECT pCritSect = &pDevIns->Internal.s.pDut->CritSectNop;
+
+ LogFlow(("pdmR3DevHlp_CritSectGetNop: caller='%s'/%d: return %p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
+ return pCritSect;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSetDeviceCritSect} */
+static DECLCALLBACK(int) pdmR3DevHlp_SetDeviceCritSect(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
+{
+ /*
+ * Validate input.
+ */
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertPtrReturn(pCritSect, VERR_INVALID_POINTER);
+
+ LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: pCritSect=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
+
+ pDevIns->pCritSectRoR3 = pCritSect;
+ LogFlow(("pdmR3DevHlp_SetDeviceCritSect: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectYield} */
+static DECLCALLBACK(bool) pdmR3DevHlp_CritSectYield(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ RT_NOREF(pDevIns, pCritSect);
+ AssertFailed();
+ return false;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectEnter} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ RT_NOREF(pDevIns, rcBusy);
+ return RTCritSectEnter(&pCritSect->s.CritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectEnterDebug} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ RT_NOREF(pDevIns, rcBusy, uId, RT_SRC_POS_ARGS);
+ return RTCritSectEnter(&pCritSect->s.CritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectTryEnter} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectTryEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ RT_NOREF(pDevIns, pCritSect);
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectTryEnterDebug} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectTryEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ RT_NOREF(pDevIns, pCritSect, uId, RT_SRC_POS_ARGS);
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectLeave} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectLeave(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ return RTCritSectLeave(&pCritSect->s.CritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectIsOwner} */
+static DECLCALLBACK(bool) pdmR3DevHlp_CritSectIsOwner(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ return RTCritSectIsOwner(&pCritSect->s.CritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectIsInitialized} */
+static DECLCALLBACK(bool) pdmR3DevHlp_CritSectIsInitialized(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ RT_NOREF(pDevIns, pCritSect);
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ AssertFailed();
+ return false;
+#else
+ return true;
+#endif
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectHasWaiters} */
+static DECLCALLBACK(bool) pdmR3DevHlp_CritSectHasWaiters(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pDevIns, pCritSect);
+ AssertFailed();
+ return false;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectGetRecursion} */
+static DECLCALLBACK(uint32_t) pdmR3DevHlp_CritSectGetRecursion(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ RT_NOREF(pDevIns, pCritSect);
+ AssertFailed();
+ return 0;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectScheduleExitEvent} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectScheduleExitEvent(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect,
+ SUPSEMEVENT hEventToSignal)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ RT_NOREF(pDevIns, pCritSect, hEventToSignal);
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectDelete} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectDelete(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ RT_NOREF(pDevIns, pCritSect);
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwInit} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwInit(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, RT_SRC_POS_DECL,
+ const char *pszNameFmt, va_list va)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_CritSectRwInit: caller='%s'/%d: pCritSect=%p pszNameFmt=%p:{%s}\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pCritSect, pszNameFmt, pszNameFmt));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed(); RT_NOREF(RT_SRC_POS_ARGS, va);
+
+ LogFlow(("pdmR3DevHlp_CritSectInit: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwDelete} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwDelete(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed(); RT_NOREF(pCritSect);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwEnterShared} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwEnterShared(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed(); RT_NOREF(pCritSect, rcBusy);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwEnterSharedDebug} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwEnterSharedDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy,
+ RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed(); RT_NOREF(pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwTryEnterShared} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwTryEnterShared(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed(); RT_NOREF(pCritSect);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwTryEnterSharedDebug} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwTryEnterSharedDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect,
+ RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed(); RT_NOREF(pCritSect, uId, RT_SRC_POS_ARGS);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwLeaveShared} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwLeaveShared(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed(); RT_NOREF(pCritSect);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwEnterExcl} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwEnterExcl(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed(); RT_NOREF(pCritSect, rcBusy);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwEnterExclDebug} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwEnterExclDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy,
+ RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed(); RT_NOREF(pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwTryEnterExcl} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwTryEnterExcl(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed(); RT_NOREF(pCritSect);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwTryEnterExclDebug} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwTryEnterExclDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect,
+ RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed(); RT_NOREF(pCritSect, uId, RT_SRC_POS_ARGS);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwLeaveExcl} */
+static DECLCALLBACK(int) pdmR3DevHlp_CritSectRwLeaveExcl(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed(); RT_NOREF(pCritSect);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwIsWriteOwner} */
+static DECLCALLBACK(bool) pdmR3DevHlp_CritSectRwIsWriteOwner(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed(); RT_NOREF(pCritSect);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwIsReadOwner} */
+static DECLCALLBACK(bool) pdmR3DevHlp_CritSectRwIsReadOwner(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, bool fWannaHear)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed(); RT_NOREF(pCritSect, fWannaHear);
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwGetWriteRecursion} */
+static DECLCALLBACK(uint32_t) pdmR3DevHlp_CritSectRwGetWriteRecursion(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pDevIns, pCritSect);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwGetWriterReadRecursion} */
+static DECLCALLBACK(uint32_t) pdmR3DevHlp_CritSectRwGetWriterReadRecursion(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pDevIns, pCritSect);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwGetReadCount} */
+static DECLCALLBACK(uint32_t) pdmR3DevHlp_CritSectRwGetReadCount(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pDevIns, pCritSect);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCritSectRwIsInitialized} */
+static DECLCALLBACK(bool) pdmR3DevHlp_CritSectRwIsInitialized(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pDevIns, pCritSect);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_ThreadCreate(PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
+ PFNPDMTHREADWAKEUPDEV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
+
+ int rc = tstDevPdmR3ThreadCreateDevice(pDevIns->Internal.s.pDut, pDevIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
+
+ LogFlow(("pdmR3DevHlp_ThreadCreate: caller='%s'/%d: returns %Rrc *ppThread=%RTthrd\n", pDevIns->pReg->szName, pDevIns->iInstance,
+ rc, *ppThread));
+ return rc;
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_ThreadDestroy(PPDMTHREAD pThread, int *pRcThread)
+{
+ return tstDevPdmR3ThreadDestroy(pThread, pRcThread);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_ThreadIAmSuspending(PPDMTHREAD pThread)
+{
+ return tstDevPdmR3ThreadIAmSuspending(pThread);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_ThreadIamRunning(PPDMTHREAD pThread)
+{
+ return tstDevPdmR3ThreadIAmRunning(pThread);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_ThreadSleep(PPDMTHREAD pThread, RTMSINTERVAL cMillies)
+{
+ return tstDevPdmR3ThreadSleep(pThread, cMillies);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_ThreadSuspend(PPDMTHREAD pThread)
+{
+ return tstDevPdmR3ThreadSuspend(pThread);
+}
+
+
+static DECLCALLBACK(int) pdmR3DevHlp_ThreadResume(PPDMTHREAD pThread)
+{
+ return tstDevPdmR3ThreadResume(pThread);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSetAsyncNotification} */
+static DECLCALLBACK(int) pdmR3DevHlp_SetAsyncNotification(PPDMDEVINS pDevIns, PFNPDMDEVASYNCNOTIFY pfnAsyncNotify)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: pfnAsyncNotify=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pfnAsyncNotify));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertStmt(pfnAsyncNotify, rc = VERR_INVALID_PARAMETER);
+#if 0
+ AssertStmt(!pDevIns->Internal.s.pfnAsyncNotify, rc = VERR_WRONG_ORDER);
+ AssertStmt(pDevIns->Internal.s.fIntFlags & (PDMDEVINSINT_FLAGS_SUSPENDED | PDMDEVINSINT_FLAGS_RESET), rc = VERR_WRONG_ORDER);
+#endif
+
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnAsyncNotificationCompleted} */
+static DECLCALLBACK(void) pdmR3DevHlp_AsyncNotificationCompleted(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ AssertFailed();
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnRTCRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_RTCRegister(PPDMDEVINS pDevIns, PCPDMRTCREG pRtcReg, PCPDMRTCHLP *ppRtcHlp)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: pRtcReg=%p:{.u32Version=%#x, .pfnWrite=%p, .pfnRead=%p} ppRtcHlp=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pRtcReg, pRtcReg->u32Version, pRtcReg->pfnWrite,
+ pRtcReg->pfnWrite, ppRtcHlp));
+
+ /*
+ * Validate input.
+ */
+ if (pRtcReg->u32Version != PDM_RTCREG_VERSION)
+ {
+ AssertMsgFailed(("u32Version=%#x expected %#x\n", pRtcReg->u32Version,
+ PDM_RTCREG_VERSION));
+ LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (version)\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
+ return VERR_INVALID_PARAMETER;
+ }
+ if ( !pRtcReg->pfnWrite
+ || !pRtcReg->pfnRead)
+ {
+ Assert(pRtcReg->pfnWrite);
+ Assert(pRtcReg->pfnRead);
+ LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ if (!ppRtcHlp)
+ {
+ Assert(ppRtcHlp);
+ LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc (ppRtcHlp)\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_RTCRegister: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDMARegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_DMARegister(PPDMDEVINS pDevIns, unsigned uChannel, PFNDMATRANSFERHANDLER pfnTransferHandler, void *pvUser)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: uChannel=%d pfnTransferHandler=%p pvUser=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pfnTransferHandler, pvUser));
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_DMARegister: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDMAReadMemory} */
+static DECLCALLBACK(int) pdmR3DevHlp_DMAReadMemory(PPDMDEVINS pDevIns, unsigned uChannel, void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbRead)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbRead=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbRead));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_DMAReadMemory: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDMAWriteMemory} */
+static DECLCALLBACK(int) pdmR3DevHlp_DMAWriteMemory(PPDMDEVINS pDevIns, unsigned uChannel, const void *pvBuffer, uint32_t off, uint32_t cbBlock, uint32_t *pcbWritten)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: uChannel=%d pvBuffer=%p off=%#x cbBlock=%#x pcbWritten=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, uChannel, pvBuffer, off, cbBlock, pcbWritten));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_DMAWriteMemory: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDMASetDREQ} */
+static DECLCALLBACK(int) pdmR3DevHlp_DMASetDREQ(PPDMDEVINS pDevIns, unsigned uChannel, unsigned uLevel)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: uChannel=%d uLevel=%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, uChannel, uLevel));
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_DMASetDREQ: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDMAGetChannelMode} */
+static DECLCALLBACK(uint8_t) pdmR3DevHlp_DMAGetChannelMode(PPDMDEVINS pDevIns, unsigned uChannel)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: uChannel=%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, uChannel));
+
+ uint8_t u8Mode = (3 << 2); /* Invalid mode. */
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_DMAGetChannelMode: caller='%s'/%d: returns %#04x\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, u8Mode));
+ return u8Mode;
+}
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDMASchedule} */
+static DECLCALLBACK(void) pdmR3DevHlp_DMASchedule(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DMASchedule: caller='%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+
+ AssertFailed();
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSWrite} */
+static DECLCALLBACK(int) pdmR3DevHlp_CMOSWrite(PPDMDEVINS pDevIns, unsigned iReg, uint8_t u8Value)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x u8Value=%#04x\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, iReg, u8Value));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCMOSRead} */
+static DECLCALLBACK(int) pdmR3DevHlp_CMOSRead(PPDMDEVINS pDevIns, unsigned iReg, uint8_t *pu8Value)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: iReg=%#04x pu8Value=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, iReg, pu8Value));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_CMOSWrite: caller='%s'/%d: return %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnAssertEMT} */
+static DECLCALLBACK(bool) pdmR3DevHlp_AssertEMT(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ char szMsg[100];
+ RTStrPrintf(szMsg, sizeof(szMsg), "AssertEMT '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
+ RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
+ AssertBreakpoint();
+ return false;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnAssertOther} */
+static DECLCALLBACK(bool) pdmR3DevHlp_AssertOther(PPDMDEVINS pDevIns, const char *pszFile, unsigned iLine, const char *pszFunction)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ char szMsg[100];
+ RTStrPrintf(szMsg, sizeof(szMsg), "AssertOther '%s'/%d\n", pDevIns->pReg->szName, pDevIns->iInstance);
+ RTAssertMsg1Weak(szMsg, iLine, pszFile, pszFunction);
+ AssertBreakpoint();
+ return false;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetRCInterfaceSymbols} */
+static DECLCALLBACK(int) pdmR3DevHlp_LdrGetRCInterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
+ const char *pszSymPrefix, const char *pszSymList)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
+ pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnLdrGetR0InterfaceSymbols} */
+static DECLCALLBACK(int) pdmR3DevHlp_LdrGetR0InterfaceSymbols(PPDMDEVINS pDevIns, void *pvInterface, size_t cbInterface,
+ const char *pszSymPrefix, const char *pszSymList)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
+ pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnCallR0} */
+static DECLCALLBACK(int) pdmR3DevHlp_CallR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: uOperation=%#x u64Arg=%#RX64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, uOperation, u64Arg));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
+ pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetSuspendReason} */
+static DECLCALLBACK(VMSUSPENDREASON) pdmR3DevHlp_VMGetSuspendReason(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ VMSUSPENDREASON enmReason = VMSUSPENDREASON_INVALID;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_VMGetSuspendReason: caller='%s'/%d: returns %d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
+ return enmReason;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMGetResumeReason} */
+static DECLCALLBACK(VMRESUMEREASON) pdmR3DevHlp_VMGetResumeReason(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ VMRESUMEREASON enmReason = VMRESUMEREASON_INVALID;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_VMGetResumeReason: caller='%s'/%d: returns %d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, enmReason));
+ return enmReason;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnGetUVM} */
+static DECLCALLBACK(PUVM) pdmR3DevHlp_GetUVM(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ AssertFailed();
+ LogFlow(("pdmR3DevHlp_GetUVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, NULL));
+ return NULL;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnGetVM} */
+static DECLCALLBACK(PVMCC) pdmR3DevHlp_GetVM(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns->Internal.s.pDut->pVm));
+ return pDevIns->Internal.s.pDut->pVm;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnGetVMCPU} */
+static DECLCALLBACK(PVMCPU) pdmR3DevHlp_GetVMCPU(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ AssertFailed();
+ LogFlow(("pdmR3DevHlp_GetVMCPU: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, NULL));
+ return NULL;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnGetCurrentCpuId} */
+static DECLCALLBACK(VMCPUID) pdmR3DevHlp_GetCurrentCpuId(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ VMCPUID idCpu = 0;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_GetCurrentCpuId: caller='%s'/%d for CPU %u\n", pDevIns->pReg->szName, pDevIns->iInstance, idCpu));
+ return idCpu;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPCIBusRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_PCIBusRegister(PPDMDEVINS pDevIns, PPDMPCIBUSREGR3 pPciBusReg,
+ PCPDMPCIHLPR3 *ppPciHlp, uint32_t *piBus)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: pPciBusReg=%p:{.u32Version=%#x, .pfnRegisterR3=%p, .pfnIORegionRegisterR3=%p, "
+ ".pfnInterceptConfigAccesses=%p, pfnConfigRead=%p, pfnConfigWrite=%p, .pfnSetIrqR3=%p, .u32EndVersion=%#x} ppPciHlpR3=%p piBus=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->pfnRegisterR3,
+ pPciBusReg->pfnIORegionRegisterR3, pPciBusReg->pfnInterceptConfigAccesses, pPciBusReg->pfnConfigRead,
+ pPciBusReg->pfnConfigWrite, pPciBusReg->pfnSetIrqR3, pPciBusReg->u32EndVersion, ppPciHlp, piBus));
+
+ /*
+ * Validate the structure and output parameters.
+ */
+ AssertLogRelMsgReturn(pPciBusReg->u32Version == PDM_PCIBUSREGR3_VERSION,
+ ("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGR3_VERSION),
+ VERR_INVALID_PARAMETER);
+ AssertPtrReturn(pPciBusReg->pfnRegisterR3, VERR_INVALID_PARAMETER);
+ AssertPtrNullReturn(pPciBusReg->pfnRegisterMsiR3, VERR_INVALID_POINTER);
+ AssertPtrReturn(pPciBusReg->pfnIORegionRegisterR3, VERR_INVALID_POINTER);
+ AssertPtrReturn(pPciBusReg->pfnInterceptConfigAccesses, VERR_INVALID_POINTER);
+ AssertPtrReturn(pPciBusReg->pfnConfigWrite, VERR_INVALID_POINTER);
+ AssertPtrReturn(pPciBusReg->pfnConfigRead, VERR_INVALID_POINTER);
+ AssertPtrReturn(pPciBusReg->pfnSetIrqR3, VERR_INVALID_POINTER);
+ AssertLogRelMsgReturn(pPciBusReg->u32EndVersion == PDM_PCIBUSREGR3_VERSION,
+ ("u32Version=%#x expected %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGR3_VERSION),
+ VERR_INVALID_PARAMETER);
+ AssertPtrReturn(ppPciHlp, VERR_INVALID_POINTER);
+ AssertPtrNullReturn(piBus, VERR_INVALID_POINTER);
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ Log(("PDM: Registered PCI bus device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
+
+ LogFlow(("pdmR3DevHlp_PCIBusRegister: caller='%s'/%d: returns %Rrc *piBus=%u\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *piBus));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnIommuRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_IommuRegister(PPDMDEVINS pDevIns, PPDMIOMMUREGR3 pIommuReg, PCPDMIOMMUHLPR3 *ppIommuHlp,
+ uint32_t *pidxIommu)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_IommuRegister: caller='%s'/%d: pIommuReg=%p:{.u32Version=%#x, .u32TheEnd=%#x } ppIommuHlp=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pIommuReg, pIommuReg->u32Version, pIommuReg->u32TheEnd, ppIommuHlp));
+
+ /*
+ * Validate input.
+ */
+ AssertMsgReturn(pIommuReg->u32Version == PDM_IOMMUREGR3_VERSION,
+ ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIommuReg->u32Version, PDM_IOMMUREGR3_VERSION),
+ VERR_INVALID_PARAMETER);
+ AssertPtrReturn(pIommuReg->pfnMsiRemap, VERR_INVALID_POINTER);
+ AssertMsgReturn(pIommuReg->u32TheEnd == PDM_IOMMUREGR3_VERSION,
+ ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIommuReg->u32TheEnd, PDM_IOMMUREGR3_VERSION),
+ VERR_INVALID_PARAMETER);
+ AssertPtrReturn(ppIommuHlp, VERR_INVALID_POINTER);
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed(); RT_NOREF(pidxIommu);
+ Log(("PDM: Registered IOMMU device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
+
+ LogFlow(("pdmR3DevHlp_IommuRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPICRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_PICRegister(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnGetInterrupt=%p, .u32TheEnd=%#x } ppPicHlp=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrq, pPicReg->pfnGetInterrupt, pPicReg->u32TheEnd, ppPicHlp));
+
+ /*
+ * Validate input.
+ */
+ AssertMsgReturn(pPicReg->u32Version == PDM_PICREG_VERSION,
+ ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32Version, PDM_PICREG_VERSION),
+ VERR_INVALID_PARAMETER);
+ AssertPtrReturn(pPicReg->pfnSetIrq, VERR_INVALID_POINTER);
+ AssertPtrReturn(pPicReg->pfnGetInterrupt, VERR_INVALID_POINTER);
+ AssertMsgReturn(pPicReg->u32TheEnd == PDM_PICREG_VERSION,
+ ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32TheEnd, PDM_PICREG_VERSION),
+ VERR_INVALID_PARAMETER);
+ AssertPtrReturn(ppPicHlp, VERR_INVALID_POINTER);
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+ Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
+
+ LogFlow(("pdmR3DevHlp_PICRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnApicRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_ApicRegister(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_ApicRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnIoApicRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_IoApicRegister(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_IoApicRegister: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnSendMsi=%p, .pfnSetEoi=%p, .u32TheEnd=%#x } ppIoApicHlp=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrq, pIoApicReg->pfnSendMsi, pIoApicReg->pfnSetEoi, pIoApicReg->u32TheEnd, ppIoApicHlp));
+
+ /*
+ * Validate input.
+ */
+ AssertMsgReturn(pIoApicReg->u32Version == PDM_IOAPICREG_VERSION,
+ ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32Version, PDM_IOAPICREG_VERSION),
+ VERR_VERSION_MISMATCH);
+ AssertPtrReturn(pIoApicReg->pfnSetIrq, VERR_INVALID_POINTER);
+ AssertPtrReturn(pIoApicReg->pfnSendMsi, VERR_INVALID_POINTER);
+ AssertPtrReturn(pIoApicReg->pfnSetEoi, VERR_INVALID_POINTER);
+ AssertMsgReturn(pIoApicReg->u32TheEnd == PDM_IOAPICREG_VERSION,
+ ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32TheEnd, PDM_IOAPICREG_VERSION),
+ VERR_VERSION_MISMATCH);
+ AssertPtrReturn(ppIoApicHlp, VERR_INVALID_POINTER);
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_IoApicRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnHpetRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_HpetRegister(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR3 *ppHpetHlpR3)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_HpetRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
+
+ /*
+ * Validate input.
+ */
+ AssertMsgReturn(pHpetReg->u32Version == PDM_HPETREG_VERSION,
+ ("%s/%u: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pHpetReg->u32Version, PDM_HPETREG_VERSION),
+ VERR_VERSION_MISMATCH);
+ AssertPtrReturn(ppHpetHlpR3, VERR_INVALID_POINTER);
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_HpetRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPciRawRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_PciRawRegister(PPDMDEVINS pDevIns, PPDMPCIRAWREG pPciRawReg, PCPDMPCIRAWHLPR3 *ppPciRawHlpR3)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
+ LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
+
+ /*
+ * Validate input.
+ */
+ if (pPciRawReg->u32Version != PDM_PCIRAWREG_VERSION)
+ {
+ AssertMsgFailed(("u32Version=%#x expected %#x\n", pPciRawReg->u32Version, PDM_PCIRAWREG_VERSION));
+ LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (version)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ if (!ppPciRawHlpR3)
+ {
+ Assert(ppPciRawHlpR3);
+ LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc (ppPciRawHlpR3)\n", pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_PciRawRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnDMACRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_DMACRegister(PPDMDEVINS pDevIns, PPDMDMACREG pDmacReg, PCPDMDMACHLP *ppDmacHlp)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: pDmacReg=%p:{.u32Version=%#x, .pfnRun=%p, .pfnRegister=%p, .pfnReadMemory=%p, .pfnWriteMemory=%p, .pfnSetDREQ=%p, .pfnGetChannelMode=%p} ppDmacHlp=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pDmacReg, pDmacReg->u32Version, pDmacReg->pfnRun, pDmacReg->pfnRegister,
+ pDmacReg->pfnReadMemory, pDmacReg->pfnWriteMemory, pDmacReg->pfnSetDREQ, pDmacReg->pfnGetChannelMode, ppDmacHlp));
+
+ /*
+ * Validate input.
+ */
+ if (pDmacReg->u32Version != PDM_DMACREG_VERSION)
+ {
+ AssertMsgFailed(("u32Version=%#x expected %#x\n", pDmacReg->u32Version,
+ PDM_DMACREG_VERSION));
+ LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (version)\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
+ return VERR_INVALID_PARAMETER;
+ }
+ if ( !pDmacReg->pfnRun
+ || !pDmacReg->pfnRegister
+ || !pDmacReg->pfnReadMemory
+ || !pDmacReg->pfnWriteMemory
+ || !pDmacReg->pfnSetDREQ
+ || !pDmacReg->pfnGetChannelMode)
+ {
+ Assert(pDmacReg->pfnRun);
+ Assert(pDmacReg->pfnRegister);
+ Assert(pDmacReg->pfnReadMemory);
+ Assert(pDmacReg->pfnWriteMemory);
+ Assert(pDmacReg->pfnSetDREQ);
+ Assert(pDmacReg->pfnGetChannelMode);
+ LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ if (!ppDmacHlp)
+ {
+ Assert(ppDmacHlp);
+ LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc (ppDmacHlp)\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_DMACRegister: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/**
+ * @copydoc PDMDEVHLPR3::pfnRegisterVMMDevHeap
+ */
+static DECLCALLBACK(int) pdmR3DevHlp_RegisterVMMDevHeap(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTR3PTR pvHeap, unsigned cbHeap)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: GCPhys=%RGp pvHeap=%p cbHeap=%#x\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, GCPhys, pvHeap, cbHeap));
+
+#ifndef VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+#else
+ int rc = VINF_SUCCESS;
+#endif
+
+ LogFlow(("pdmR3DevHlp_RegisterVMMDevHeap: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/**
+ * @interface_method_impl{PDMDEVHLPR3,pfnFirmwareRegister}
+ */
+static DECLCALLBACK(int) pdmR3DevHlp_FirmwareRegister(PPDMDEVINS pDevIns, PCPDMFWREG pFwReg, PCPDMFWHLPR3 *ppFwHlp)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: pFWReg=%p:{.u32Version=%#x, .pfnIsHardReset=%p, .u32TheEnd=%#x} ppFwHlp=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pFwReg, pFwReg->u32Version, pFwReg->pfnIsHardReset, pFwReg->u32TheEnd, ppFwHlp));
+
+ /*
+ * Validate input.
+ */
+ if (pFwReg->u32Version != PDM_FWREG_VERSION)
+ {
+ AssertMsgFailed(("u32Version=%#x expected %#x\n", pFwReg->u32Version, PDM_FWREG_VERSION));
+ LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (version)\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
+ return VERR_INVALID_PARAMETER;
+ }
+ if (!pFwReg->pfnIsHardReset)
+ {
+ Assert(pFwReg->pfnIsHardReset);
+ LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (callbacks)\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ if (!ppFwHlp)
+ {
+ Assert(ppFwHlp);
+ LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc (ppFwHlp)\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, VERR_INVALID_PARAMETER));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_FirmwareRegister: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMReset} */
+static DECLCALLBACK(int) pdmR3DevHlp_VMReset(PPDMDEVINS pDevIns, uint32_t fFlags)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: fFlags=%#x\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, fFlags));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_VMReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspend} */
+static DECLCALLBACK(int) pdmR3DevHlp_VMSuspend(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d:\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_VMSuspend: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMSuspendSaveAndPowerOff} */
+static DECLCALLBACK(int) pdmR3DevHlp_VMSuspendSaveAndPowerOff(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d:\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_VMSuspendSaveAndPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMPowerOff} */
+static DECLCALLBACK(int) pdmR3DevHlp_VMPowerOff(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d:\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_VMPowerOff: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnA20IsEnabled} */
+static DECLCALLBACK(bool) pdmR3DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ bool fRc = false;
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_A20IsEnabled: caller='%s'/%d: returns %d\n", pDevIns->pReg->szName, pDevIns->iInstance, fRc));
+ return fRc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnA20Set} */
+static DECLCALLBACK(void) pdmR3DevHlp_A20Set(PPDMDEVINS pDevIns, bool fEnable)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_A20Set: caller='%s'/%d: fEnable=%d\n", pDevIns->pReg->szName, pDevIns->iInstance, fEnable));
+ AssertFailed();
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnGetCpuId} */
+static DECLCALLBACK(void) pdmR3DevHlp_GetCpuId(PPDMDEVINS pDevIns, uint32_t iLeaf,
+ uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: iLeaf=%d pEax=%p pEbx=%p pEcx=%p pEdx=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, iLeaf, pEax, pEbx, pEcx, pEdx));
+ AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx);
+
+ AssertFailed();
+
+ LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, *pEax, *pEbx, *pEcx, *pEdx));
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnGetMainExecutionEngine} */
+static DECLCALLBACK(uint8_t) pdmR3DevHlp_GetMainExecutionEngine(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ //VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
+ LogFlow(("pdmR3DevHlp_GetMainExecutionEngine: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
+ return VM_EXEC_ENGINE_NOT_SET;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPGMHandlerPhysicalRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_PGMHandlerPhysicalRegister(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS GCPhysLast,
+ PGMPHYSHANDLERTYPE hType, RTR3PTR pvUserR3, RTR0PTR pvUserR0,
+ RTRCPTR pvUserRC, R3PTRTYPE(const char *) pszDesc)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(GCPhys, GCPhysLast, hType, pvUserR3, pvUserR0, pvUserRC, pszDesc);
+ AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+ return VERR_ACCESS_DENIED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPGMHandlerPhysicalDeregister} */
+static DECLCALLBACK(int) pdmR3DevHlp_PGMHandlerPhysicalDeregister(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(GCPhys);
+ AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+ return VERR_ACCESS_DENIED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPGMHandlerPhysicalPageTempOff} */
+static DECLCALLBACK(int) pdmR3DevHlp_PGMHandlerPhysicalPageTempOff(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(GCPhys, GCPhysPage);
+ AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+ return VERR_ACCESS_DENIED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnPGMHandlerPhysicalReset} */
+static DECLCALLBACK(int) pdmR3DevHlp_PGMHandlerPhysicalReset(PPDMDEVINS pDevIns, RTGCPHYS GCPhys)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(GCPhys);
+ AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+ return VERR_ACCESS_DENIED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMMRegisterPatchMemory} */
+static DECLCALLBACK(int) pdmR3DevHlp_VMMRegisterPatchMemory(PPDMDEVINS pDevIns, RTGCPTR GCPtrPatchMem, uint32_t cbPatchMem)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(GCPtrPatchMem, cbPatchMem);
+ AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+ return VERR_ACCESS_DENIED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnVMMDeregisterPatchMemory} */
+static DECLCALLBACK(int) pdmR3DevHlp_VMMDeregisterPatchMemory(PPDMDEVINS pDevIns, RTGCPTR GCPtrPatchMem, uint32_t cbPatchMem)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(GCPtrPatchMem, cbPatchMem);
+ AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+ return VERR_ACCESS_DENIED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSharedModuleRegister} */
+static DECLCALLBACK(int) pdmR3DevHlp_SharedModuleRegister(PPDMDEVINS pDevIns, VBOXOSFAMILY enmGuestOS, char *pszModuleName, char *pszVersion,
+ RTGCPTR GCBaseAddr, uint32_t cbModule,
+ uint32_t cRegions, VMMDEVSHAREDREGIONDESC const *paRegions)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(enmGuestOS, pszModuleName, pszVersion, GCBaseAddr, cbModule, cRegions, paRegions);
+ AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+ return VERR_ACCESS_DENIED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSharedModuleUnregister} */
+static DECLCALLBACK(int) pdmR3DevHlp_SharedModuleUnregister(PPDMDEVINS pDevIns, char *pszModuleName, char *pszVersion,
+ RTGCPTR GCBaseAddr, uint32_t cbModule)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pszModuleName, pszVersion, GCBaseAddr, cbModule);
+ AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+ return VERR_ACCESS_DENIED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSharedModuleGetPageState} */
+static DECLCALLBACK(int) pdmR3DevHlp_SharedModuleGetPageState(PPDMDEVINS pDevIns, RTGCPTR GCPtrPage, bool *pfShared, uint64_t *pfPageFlags)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(GCPtrPage, pfShared, pfPageFlags);
+ AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+ return VERR_ACCESS_DENIED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnSharedModuleCheckAll} */
+static DECLCALLBACK(int) pdmR3DevHlp_SharedModuleCheckAll(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+ return VERR_ACCESS_DENIED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnQueryLun} */
+static DECLCALLBACK(int) pdmR3DevHlp_QueryLun(PPDMDEVINS pDevIns, const char *pszDevice, unsigned iInstance, unsigned iLun, PPDMIBASE *ppBase)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pszDevice, iInstance, iLun, ppBase);
+ AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+ return VERR_ACCESS_DENIED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnGIMDeviceRegister} */
+static DECLCALLBACK(void) pdmR3DevHlp_GIMDeviceRegister(PPDMDEVINS pDevIns, PGIMDEBUG pDbg)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pDbg);
+ AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnGIMGetDebugSetup} */
+static DECLCALLBACK(int) pdmR3DevHlp_GIMGetDebugSetup(PPDMDEVINS pDevIns, PGIMDEBUGSETUP pDbgSetup)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pDbgSetup);
+ AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+ return VERR_ACCESS_DENIED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR3,pfnGIMGetMmio2Regions} */
+static DECLCALLBACK(PGIMMMIO2REGION) pdmR3DevHlp_GIMGetMmio2Regions(PPDMDEVINS pDevIns, uint32_t *pcRegions)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pcRegions);
+ AssertReleaseMsgFailed(("Untrusted device called trusted helper! '%s'/%d\n",
+ pDevIns->pReg->szName, pDevIns->iInstance));
+ return NULL;
+}
+
+const PDMDEVHLPR3 g_tstDevPdmDevHlpR3 =
+{
+ PDM_DEVHLPR3_VERSION,
+ pdmR3DevHlp_IoPortCreateEx,
+ pdmR3DevHlp_IoPortMap,
+ pdmR3DevHlp_IoPortUnmap,
+ pdmR3DevHlp_IoPortGetMappingAddress,
+ pdmR3DevHlp_IoPortWrite,
+ pdmR3DevHlp_MmioCreateEx,
+ pdmR3DevHlp_MmioMap,
+ pdmR3DevHlp_MmioUnmap,
+ pdmR3DevHlp_MmioReduce,
+ pdmR3DevHlp_MmioGetMappingAddress,
+ pdmR3DevHlp_Mmio2Create,
+ pdmR3DevHlp_Mmio2Destroy,
+ pdmR3DevHlp_Mmio2Map,
+ pdmR3DevHlp_Mmio2Unmap,
+ pdmR3DevHlp_Mmio2Reduce,
+ pdmR3DevHlp_Mmio2GetMappingAddress,
+ pdmR3DevHlp_Mmio2QueryAndResetDirtyBitmap,
+ pdmR3DevHlp_Mmio2ControlDirtyPageTracking,
+ pdmR3DevHlp_Mmio2ChangeRegionNo,
+ pdmR3DevHlp_MmioMapMmio2Page,
+ pdmR3DevHlp_MmioResetRegion,
+ pdmR3DevHlp_ROMRegister,
+ pdmR3DevHlp_ROMProtectShadow,
+ pdmR3DevHlp_SSMRegister,
+ pdmR3DevHlp_SSMRegisterLegacy,
+ pdmR3DevHlp_SSMPutStruct,
+ pdmR3DevHlp_SSMPutStructEx,
+ pdmR3DevHlp_SSMPutBool,
+ pdmR3DevHlp_SSMPutU8,
+ pdmR3DevHlp_SSMPutS8,
+ pdmR3DevHlp_SSMPutU16,
+ pdmR3DevHlp_SSMPutS16,
+ pdmR3DevHlp_SSMPutU32,
+ pdmR3DevHlp_SSMPutS32,
+ pdmR3DevHlp_SSMPutU64,
+ pdmR3DevHlp_SSMPutS64,
+ pdmR3DevHlp_SSMPutU128,
+ pdmR3DevHlp_SSMPutS128,
+ pdmR3DevHlp_SSMPutUInt,
+ pdmR3DevHlp_SSMPutSInt,
+ pdmR3DevHlp_SSMPutGCUInt,
+ pdmR3DevHlp_SSMPutGCUIntReg,
+ pdmR3DevHlp_SSMPutGCPhys32,
+ pdmR3DevHlp_SSMPutGCPhys64,
+ pdmR3DevHlp_SSMPutGCPhys,
+ pdmR3DevHlp_SSMPutGCPtr,
+ pdmR3DevHlp_SSMPutGCUIntPtr,
+ pdmR3DevHlp_SSMPutRCPtr,
+ pdmR3DevHlp_SSMPutIOPort,
+ pdmR3DevHlp_SSMPutSel,
+ pdmR3DevHlp_SSMPutMem,
+ pdmR3DevHlp_SSMPutStrZ,
+ pdmR3DevHlp_SSMGetStruct,
+ pdmR3DevHlp_SSMGetStructEx,
+ pdmR3DevHlp_SSMGetBool,
+ pdmR3DevHlp_SSMGetBoolV,
+ pdmR3DevHlp_SSMGetU8,
+ pdmR3DevHlp_SSMGetU8V,
+ pdmR3DevHlp_SSMGetS8,
+ pdmR3DevHlp_SSMGetS8V,
+ pdmR3DevHlp_SSMGetU16,
+ pdmR3DevHlp_SSMGetU16V,
+ pdmR3DevHlp_SSMGetS16,
+ pdmR3DevHlp_SSMGetS16V,
+ pdmR3DevHlp_SSMGetU32,
+ pdmR3DevHlp_SSMGetU32V,
+ pdmR3DevHlp_SSMGetS32,
+ pdmR3DevHlp_SSMGetS32V,
+ pdmR3DevHlp_SSMGetU64,
+ pdmR3DevHlp_SSMGetU64V,
+ pdmR3DevHlp_SSMGetS64,
+ pdmR3DevHlp_SSMGetS64V,
+ pdmR3DevHlp_SSMGetU128,
+ pdmR3DevHlp_SSMGetU128V,
+ pdmR3DevHlp_SSMGetS128,
+ pdmR3DevHlp_SSMGetS128V,
+ pdmR3DevHlp_SSMGetGCPhys32,
+ pdmR3DevHlp_SSMGetGCPhys32V,
+ pdmR3DevHlp_SSMGetGCPhys64,
+ pdmR3DevHlp_SSMGetGCPhys64V,
+ pdmR3DevHlp_SSMGetGCPhys,
+ pdmR3DevHlp_SSMGetGCPhysV,
+ pdmR3DevHlp_SSMGetUInt,
+ pdmR3DevHlp_SSMGetSInt,
+ pdmR3DevHlp_SSMGetGCUInt,
+ pdmR3DevHlp_SSMGetGCUIntReg,
+ pdmR3DevHlp_SSMGetGCPtr,
+ pdmR3DevHlp_SSMGetGCUIntPtr,
+ pdmR3DevHlp_SSMGetRCPtr,
+ pdmR3DevHlp_SSMGetIOPort,
+ pdmR3DevHlp_SSMGetSel,
+ pdmR3DevHlp_SSMGetMem,
+ pdmR3DevHlp_SSMGetStrZ,
+ pdmR3DevHlp_SSMGetStrZEx,
+ pdmR3DevHlp_SSMSkip,
+ pdmR3DevHlp_SSMSkipToEndOfUnit,
+ pdmR3DevHlp_SSMSetLoadError,
+ pdmR3DevHlp_SSMSetLoadErrorV,
+ pdmR3DevHlp_SSMSetCfgError,
+ pdmR3DevHlp_SSMSetCfgErrorV,
+ pdmR3DevHlp_SSMHandleGetStatus,
+ pdmR3DevHlp_SSMHandleGetAfter,
+ pdmR3DevHlp_SSMHandleIsLiveSave,
+ pdmR3DevHlp_SSMHandleMaxDowntime,
+ pdmR3DevHlp_SSMHandleHostBits,
+ pdmR3DevHlp_SSMHandleRevision,
+ pdmR3DevHlp_SSMHandleVersion,
+ pdmR3DevHlp_SSMHandleHostOSAndArch,
+ pdmR3DevHlp_TimerCreate,
+ pdmR3DevHlp_TimerFromMicro,
+ pdmR3DevHlp_TimerFromMilli,
+ pdmR3DevHlp_TimerFromNano,
+ pdmR3DevHlp_TimerGet,
+ pdmR3DevHlp_TimerGetFreq,
+ pdmR3DevHlp_TimerGetNano,
+ pdmR3DevHlp_TimerIsActive,
+ pdmR3DevHlp_TimerIsLockOwner,
+ pdmR3DevHlp_TimerLockClock,
+ pdmR3DevHlp_TimerLockClock2,
+ pdmR3DevHlp_TimerSet,
+ pdmR3DevHlp_TimerSetFrequencyHint,
+ pdmR3DevHlp_TimerSetMicro,
+ pdmR3DevHlp_TimerSetMillies,
+ pdmR3DevHlp_TimerSetNano,
+ pdmR3DevHlp_TimerSetRelative,
+ pdmR3DevHlp_TimerStop,
+ pdmR3DevHlp_TimerUnlockClock,
+ pdmR3DevHlp_TimerUnlockClock2,
+ pdmR3DevHlp_TimerSetCritSect,
+ pdmR3DevHlp_TimerSave,
+ pdmR3DevHlp_TimerLoad,
+ pdmR3DevHlp_TimerDestroy,
+ pdmR3DevHlp_TimerSkipLoad,
+ pdmR3DevHlp_TMUtcNow,
+ pdmR3DevHlp_CFGMExists,
+ pdmR3DevHlp_CFGMQueryType,
+ pdmR3DevHlp_CFGMQuerySize,
+ pdmR3DevHlp_CFGMQueryInteger,
+ pdmR3DevHlp_CFGMQueryIntegerDef,
+ pdmR3DevHlp_CFGMQueryString,
+ pdmR3DevHlp_CFGMQueryStringDef,
+ pdmR3DevHlp_CFGMQueryPassword,
+ pdmR3DevHlp_CFGMQueryPasswordDef,
+ pdmR3DevHlp_CFGMQueryBytes,
+ pdmR3DevHlp_CFGMQueryU64,
+ pdmR3DevHlp_CFGMQueryU64Def,
+ pdmR3DevHlp_CFGMQueryS64,
+ pdmR3DevHlp_CFGMQueryS64Def,
+ pdmR3DevHlp_CFGMQueryU32,
+ pdmR3DevHlp_CFGMQueryU32Def,
+ pdmR3DevHlp_CFGMQueryS32,
+ pdmR3DevHlp_CFGMQueryS32Def,
+ pdmR3DevHlp_CFGMQueryU16,
+ pdmR3DevHlp_CFGMQueryU16Def,
+ pdmR3DevHlp_CFGMQueryS16,
+ pdmR3DevHlp_CFGMQueryS16Def,
+ pdmR3DevHlp_CFGMQueryU8,
+ pdmR3DevHlp_CFGMQueryU8Def,
+ pdmR3DevHlp_CFGMQueryS8,
+ pdmR3DevHlp_CFGMQueryS8Def,
+ pdmR3DevHlp_CFGMQueryBool,
+ pdmR3DevHlp_CFGMQueryBoolDef,
+ pdmR3DevHlp_CFGMQueryPort,
+ pdmR3DevHlp_CFGMQueryPortDef,
+ pdmR3DevHlp_CFGMQueryUInt,
+ pdmR3DevHlp_CFGMQueryUIntDef,
+ pdmR3DevHlp_CFGMQuerySInt,
+ pdmR3DevHlp_CFGMQuerySIntDef,
+ pdmR3DevHlp_CFGMQueryPtr,
+ pdmR3DevHlp_CFGMQueryPtrDef,
+ pdmR3DevHlp_CFGMQueryGCPtr,
+ pdmR3DevHlp_CFGMQueryGCPtrDef,
+ pdmR3DevHlp_CFGMQueryGCPtrU,
+ pdmR3DevHlp_CFGMQueryGCPtrUDef,
+ pdmR3DevHlp_CFGMQueryGCPtrS,
+ pdmR3DevHlp_CFGMQueryGCPtrSDef,
+ pdmR3DevHlp_CFGMQueryStringAlloc,
+ pdmR3DevHlp_CFGMQueryStringAllocDef,
+ pdmR3DevHlp_CFGMGetParent,
+ pdmR3DevHlp_CFGMGetChild,
+ pdmR3DevHlp_CFGMGetChildF,
+ pdmR3DevHlp_CFGMGetChildFV,
+ pdmR3DevHlp_CFGMGetFirstChild,
+ pdmR3DevHlp_CFGMGetNextChild,
+ pdmR3DevHlp_CFGMGetName,
+ pdmR3DevHlp_CFGMGetNameLen,
+ pdmR3DevHlp_CFGMAreChildrenValid,
+ pdmR3DevHlp_CFGMGetFirstValue,
+ pdmR3DevHlp_CFGMGetNextValue,
+ pdmR3DevHlp_CFGMGetValueName,
+ pdmR3DevHlp_CFGMGetValueNameLen,
+ pdmR3DevHlp_CFGMGetValueType,
+ pdmR3DevHlp_CFGMAreValuesValid,
+ pdmR3DevHlp_CFGMValidateConfig,
+ pdmR3DevHlp_PhysRead,
+ pdmR3DevHlp_PhysWrite,
+ pdmR3DevHlp_PhysGCPhys2CCPtr,
+ pdmR3DevHlp_PhysGCPhys2CCPtrReadOnly,
+ pdmR3DevHlp_PhysReleasePageMappingLock,
+ pdmR3DevHlp_PhysReadGCVirt,
+ pdmR3DevHlp_PhysWriteGCVirt,
+ pdmR3DevHlp_PhysGCPtr2GCPhys,
+ pdmR3DevHlp_PhysIsGCPhysNormal,
+ pdmR3DevHlp_PhysChangeMemBalloon,
+ pdmR3DevHlp_MMHeapAlloc,
+ pdmR3DevHlp_MMHeapAllocZ,
+ pdmR3DevHlp_MMHeapAPrintfV,
+ pdmR3DevHlp_MMHeapFree,
+ pdmR3DevHlp_MMPhysGetRamSize,
+ pdmR3DevHlp_MMPhysGetRamSizeBelow4GB,
+ pdmR3DevHlp_MMPhysGetRamSizeAbove4GB,
+ pdmR3DevHlp_VMState,
+ pdmR3DevHlp_VMTeleportedAndNotFullyResumedYet,
+ pdmR3DevHlp_VMSetErrorV,
+ pdmR3DevHlp_VMSetRuntimeErrorV,
+ pdmR3DevHlp_VMWaitForDeviceReady,
+ pdmR3DevHlp_VMNotifyCpuDeviceReady,
+ pdmR3DevHlp_VMReqCallNoWaitV,
+ pdmR3DevHlp_VMReqPriorityCallWaitV,
+ pdmR3DevHlp_DBGFStopV,
+ pdmR3DevHlp_DBGFInfoRegister,
+ pdmR3DevHlp_DBGFInfoRegisterArgv,
+ pdmR3DevHlp_DBGFRegRegister,
+ pdmR3DevHlp_DBGFTraceBuf,
+ pdmR3DevHlp_DBGFReportBugCheck,
+ pdmR3DevHlp_DBGFCoreWrite,
+ pdmR3DevHlp_DBGFInfoLogHlp,
+ pdmR3DevHlp_DBGFRegNmQueryU64,
+ pdmR3DevHlp_DBGFRegPrintfV,
+ pdmR3DevHlp_STAMRegister,
+ pdmR3DevHlp_STAMRegisterV,
+ pdmR3DevHlp_PCIRegister,
+ pdmR3DevHlp_PCIRegisterMsi,
+ pdmR3DevHlp_PCIIORegionRegister,
+ pdmR3DevHlp_PCIInterceptConfigAccesses,
+ pdmR3DevHlp_PCIConfigWrite,
+ pdmR3DevHlp_PCIConfigRead,
+ pdmR3DevHlp_PCIPhysRead,
+ pdmR3DevHlp_PCIPhysWrite,
+ pdmR3DevHlp_PCIPhysGCPhys2CCPtr,
+ pdmR3DevHlp_PCIPhysGCPhys2CCPtrReadOnly,
+ pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtr,
+ pdmR3DevHlp_PCIPhysBulkGCPhys2CCPtrReadOnly,
+ pdmR3DevHlp_PCISetIrq,
+ pdmR3DevHlp_PCISetIrqNoWait,
+ pdmR3DevHlp_ISASetIrq,
+ pdmR3DevHlp_ISASetIrqNoWait,
+ pdmR3DevHlp_DriverAttach,
+ pdmR3DevHlp_DriverDetach,
+ pdmR3DevHlp_DriverReconfigure,
+ pdmR3DevHlp_QueueCreate,
+ pdmR3DevHlp_QueueAlloc,
+ pdmR3DevHlp_QueueInsert,
+ pdmR3DevHlp_QueueFlushIfNecessary,
+ pdmR3DevHlp_TaskCreate,
+ pdmR3DevHlp_TaskTrigger,
+ pdmR3DevHlp_SUPSemEventCreate,
+ pdmR3DevHlp_SUPSemEventClose,
+ pdmR3DevHlp_SUPSemEventSignal,
+ pdmR3DevHlp_SUPSemEventWaitNoResume,
+ pdmR3DevHlp_SUPSemEventWaitNsAbsIntr,
+ pdmR3DevHlp_SUPSemEventWaitNsRelIntr,
+ pdmR3DevHlp_SUPSemEventGetResolution,
+ pdmR3DevHlp_SUPSemEventMultiCreate,
+ pdmR3DevHlp_SUPSemEventMultiClose,
+ pdmR3DevHlp_SUPSemEventMultiSignal,
+ pdmR3DevHlp_SUPSemEventMultiReset,
+ pdmR3DevHlp_SUPSemEventMultiWaitNoResume,
+ pdmR3DevHlp_SUPSemEventMultiWaitNsAbsIntr,
+ pdmR3DevHlp_SUPSemEventMultiWaitNsRelIntr,
+ pdmR3DevHlp_SUPSemEventMultiGetResolution,
+ pdmR3DevHlp_CritSectInit,
+ pdmR3DevHlp_CritSectGetNop,
+ pdmR3DevHlp_SetDeviceCritSect,
+ pdmR3DevHlp_CritSectYield,
+ pdmR3DevHlp_CritSectEnter,
+ pdmR3DevHlp_CritSectEnterDebug,
+ pdmR3DevHlp_CritSectTryEnter,
+ pdmR3DevHlp_CritSectTryEnterDebug,
+ pdmR3DevHlp_CritSectLeave,
+ pdmR3DevHlp_CritSectIsOwner,
+ pdmR3DevHlp_CritSectIsInitialized,
+ pdmR3DevHlp_CritSectHasWaiters,
+ pdmR3DevHlp_CritSectGetRecursion,
+ pdmR3DevHlp_CritSectScheduleExitEvent,
+ pdmR3DevHlp_CritSectDelete,
+ pdmR3DevHlp_CritSectRwInit,
+ pdmR3DevHlp_CritSectRwDelete,
+ pdmR3DevHlp_CritSectRwEnterShared,
+ pdmR3DevHlp_CritSectRwEnterSharedDebug,
+ pdmR3DevHlp_CritSectRwTryEnterShared,
+ pdmR3DevHlp_CritSectRwTryEnterSharedDebug,
+ pdmR3DevHlp_CritSectRwLeaveShared,
+ pdmR3DevHlp_CritSectRwEnterExcl,
+ pdmR3DevHlp_CritSectRwEnterExclDebug,
+ pdmR3DevHlp_CritSectRwTryEnterExcl,
+ pdmR3DevHlp_CritSectRwTryEnterExclDebug,
+ pdmR3DevHlp_CritSectRwLeaveExcl,
+ pdmR3DevHlp_CritSectRwIsWriteOwner,
+ pdmR3DevHlp_CritSectRwIsReadOwner,
+ pdmR3DevHlp_CritSectRwGetWriteRecursion,
+ pdmR3DevHlp_CritSectRwGetWriterReadRecursion,
+ pdmR3DevHlp_CritSectRwGetReadCount,
+ pdmR3DevHlp_CritSectRwIsInitialized,
+ pdmR3DevHlp_ThreadCreate,
+ pdmR3DevHlp_ThreadDestroy,
+ pdmR3DevHlp_ThreadIAmSuspending,
+ pdmR3DevHlp_ThreadIamRunning,
+ pdmR3DevHlp_ThreadSleep,
+ pdmR3DevHlp_ThreadSuspend,
+ pdmR3DevHlp_ThreadResume,
+ pdmR3DevHlp_SetAsyncNotification,
+ pdmR3DevHlp_AsyncNotificationCompleted,
+ pdmR3DevHlp_RTCRegister,
+ pdmR3DevHlp_PCIBusRegister,
+ pdmR3DevHlp_IommuRegister,
+ pdmR3DevHlp_PICRegister,
+ pdmR3DevHlp_ApicRegister,
+ pdmR3DevHlp_IoApicRegister,
+ pdmR3DevHlp_HpetRegister,
+ pdmR3DevHlp_PciRawRegister,
+ pdmR3DevHlp_DMACRegister,
+ pdmR3DevHlp_DMARegister,
+ pdmR3DevHlp_DMAReadMemory,
+ pdmR3DevHlp_DMAWriteMemory,
+ pdmR3DevHlp_DMASetDREQ,
+ pdmR3DevHlp_DMAGetChannelMode,
+ pdmR3DevHlp_DMASchedule,
+ pdmR3DevHlp_CMOSWrite,
+ pdmR3DevHlp_CMOSRead,
+ pdmR3DevHlp_AssertEMT,
+ pdmR3DevHlp_AssertOther,
+ pdmR3DevHlp_LdrGetRCInterfaceSymbols,
+ pdmR3DevHlp_LdrGetR0InterfaceSymbols,
+ pdmR3DevHlp_CallR0,
+ pdmR3DevHlp_VMGetSuspendReason,
+ pdmR3DevHlp_VMGetResumeReason,
+ pdmR3DevHlp_PhysBulkGCPhys2CCPtr,
+ pdmR3DevHlp_PhysBulkGCPhys2CCPtrReadOnly,
+ pdmR3DevHlp_PhysBulkReleasePageMappingLocks,
+ pdmR3DevHlp_CpuGetGuestMicroarch,
+ pdmR3DevHlp_CpuGetGuestAddrWidths,
+ pdmR3DevHlp_CpuGetGuestScalableBusFrequency,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ pdmR3DevHlp_GetUVM,
+ pdmR3DevHlp_GetVM,
+ pdmR3DevHlp_GetVMCPU,
+ pdmR3DevHlp_GetCurrentCpuId,
+ pdmR3DevHlp_RegisterVMMDevHeap,
+ pdmR3DevHlp_FirmwareRegister,
+ pdmR3DevHlp_VMReset,
+ pdmR3DevHlp_VMSuspend,
+ pdmR3DevHlp_VMSuspendSaveAndPowerOff,
+ pdmR3DevHlp_VMPowerOff,
+ pdmR3DevHlp_A20IsEnabled,
+ pdmR3DevHlp_A20Set,
+ pdmR3DevHlp_GetCpuId,
+ pdmR3DevHlp_GetMainExecutionEngine,
+ pdmR3DevHlp_TMTimeVirtGet,
+ pdmR3DevHlp_TMTimeVirtGetFreq,
+ pdmR3DevHlp_TMTimeVirtGetNano,
+ pdmR3DevHlp_TMCpuTicksPerSecond,
+ pdmR3DevHlp_GetSupDrvSession,
+ pdmR3DevHlp_QueryGenericUserObject,
+ pdmR3DevHlp_PGMHandlerPhysicalTypeRegister,
+ pdmR3DevHlp_PGMHandlerPhysicalRegister,
+ pdmR3DevHlp_PGMHandlerPhysicalDeregister,
+ pdmR3DevHlp_PGMHandlerPhysicalPageTempOff,
+ pdmR3DevHlp_PGMHandlerPhysicalReset,
+ pdmR3DevHlp_VMMRegisterPatchMemory,
+ pdmR3DevHlp_VMMDeregisterPatchMemory,
+ pdmR3DevHlp_SharedModuleRegister,
+ pdmR3DevHlp_SharedModuleUnregister,
+ pdmR3DevHlp_SharedModuleGetPageState,
+ pdmR3DevHlp_SharedModuleCheckAll,
+ pdmR3DevHlp_QueryLun,
+ pdmR3DevHlp_GIMDeviceRegister,
+ pdmR3DevHlp_GIMGetDebugSetup,
+ pdmR3DevHlp_GIMGetMmio2Regions,
+ PDM_DEVHLPR3_VERSION /* the end */
+};
+
diff --git a/src/VBox/Devices/testcase/tstDevicePdmDevHlpR0.cpp b/src/VBox/Devices/testcase/tstDevicePdmDevHlpR0.cpp
new file mode 100644
index 00000000..5a990c72
--- /dev/null
+++ b/src/VBox/Devices/testcase/tstDevicePdmDevHlpR0.cpp
@@ -0,0 +1,1523 @@
+/* $Id: tstDevicePdmDevHlpR0.cpp $ */
+/** @file
+ * tstDevice - Test framework for PDM devices/drivers, PDM fake R0 helper implementation.
+ */
+
+/*
+ * Copyright (C) 2021-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEFAULT /** @todo */
+#undef IN_RING3
+#undef IN_SUP_R3
+#define IN_RING0
+#define IN_SUP_R0
+#define LINUX_VERSION_CODE 0
+#define KERNEL_VERSION(a,b,c) 1
+#include <iprt/linux/version.h>
+#include <VBox/types.h>
+#include <VBox/version.h>
+#include <VBox/vmm/pdmpci.h>
+
+#include <iprt/assert.h>
+#include <iprt/mem.h>
+#include <iprt/rand.h>
+#include <iprt/string.h>
+
+#include "tstDeviceInternal.h"
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+
+/* Temporarily until the stubs got implemented. */
+#define VBOX_TSTDEV_NOT_IMPLEMENTED_STUBS_FAKE_SUCCESS 1
+
+/** @def PDMDEV_ASSERT_DEVINS
+ * Asserts the validity of the device instance.
+ */
+#ifdef VBOX_STRICT
+# define PDMDEV_ASSERT_DEVINS(pDevIns) \
+ do { \
+ AssertPtr(pDevIns); \
+ Assert(pDevIns->u32Version == PDM_DEVINS_VERSION); \
+ Assert(pDevIns->CTX_SUFF(pvInstanceDataFor) == (void *)&pDevIns->achInstanceData[0]); \
+ } while (0)
+#else
+# define PDMDEV_ASSERT_DEVINS(pDevIns) do { } while (0)
+#endif
+
+
+/** Frequency of the real clock. */
+#define TMCLOCK_FREQ_REAL UINT32_C(1000)
+/** Frequency of the virtual clock. */
+#define TMCLOCK_FREQ_VIRTUAL UINT32_C(1000000000)
+
+#undef RT_VALID_PTR
+#define RT_VALID_PTR(ptr) true
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+
+
+
+/*********************************************************************************************************************************
+* Global Variables *
+*********************************************************************************************************************************/
+
+
+
+/*********************************************************************************************************************************
+* Internal Functions *
+*********************************************************************************************************************************/
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnIoPortSetUpContextEx} */
+static DECLCALLBACK(int) pdmR0DevHlp_IoPortSetUpContextEx(PPDMDEVINS pDevIns, IOMIOPORTHANDLE hIoPorts,
+ PFNIOMIOPORTNEWOUT pfnOut, PFNIOMIOPORTNEWIN pfnIn,
+ PFNIOMIOPORTNEWOUTSTRING pfnOutStr, PFNIOMIOPORTNEWINSTRING pfnInStr,
+ void *pvUser)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_IoPortSetUpContextEx: caller='%s'/%d: hIoPorts=%#x pfnOut=%p pfnIn=%p pfnOutStr=%p pfnInStr=%p pvUser=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hIoPorts, pfnOut, pfnIn, pfnOutStr, pfnInStr, pvUser));
+
+ int rc = VINF_SUCCESS;
+ PRTDEVDUTIOPORT pIoPort = (PRTDEVDUTIOPORT)hIoPorts;
+ if (RT_LIKELY(pIoPort))
+ {
+ pIoPort->pvUserR0 = pvUser;
+ pIoPort->pfnOutR0 = pfnOut;
+ pIoPort->pfnInR0 = pfnIn;
+ pIoPort->pfnOutStrR0 = pfnOutStr;
+ pIoPort->pfnInStrR0 = pfnInStr;
+ }
+ else
+ AssertReleaseFailed();
+
+ LogFlow(("pdmR0DevHlp_IoPortSetUpContextEx: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnMmioSetUpContextEx} */
+static DECLCALLBACK(int) pdmR0DevHlp_MmioSetUpContextEx(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, PFNIOMMMIONEWWRITE pfnWrite,
+ PFNIOMMMIONEWREAD pfnRead, PFNIOMMMIONEWFILL pfnFill, void *pvUser)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_MmioSetUpContextEx: caller='%s'/%d: hRegion=%#x pfnWrite=%p pfnRead=%p pfnFill=%p pvUser=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hRegion, pfnWrite, pfnRead, pfnFill, pvUser));
+
+ int rc = VINF_SUCCESS;
+ PRTDEVDUTMMIO pMmio = (PRTDEVDUTMMIO)hRegion;
+ if (RT_LIKELY(pMmio))
+ {
+ pMmio->pvUserR0 = pvUser;
+ pMmio->pfnWriteR0 = pfnWrite;
+ pMmio->pfnReadR0 = pfnRead;
+ pMmio->pfnFillR0 = pfnFill;
+ }
+ else
+ AssertReleaseFailed();
+
+ LogFlow(("pdmR0DevHlp_MmioSetUpContextEx: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnMmio2SetUpContext} */
+static DECLCALLBACK(int) pdmR0DevHlp_Mmio2SetUpContext(PPDMDEVINS pDevIns, PGMMMIO2HANDLE hRegion,
+ size_t offSub, size_t cbSub, void **ppvMapping)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_Mmio2SetUpContext: caller='%s'/%d: hRegion=%#x offSub=%#zx cbSub=%#zx ppvMapping=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hRegion, offSub, cbSub, ppvMapping));
+ *ppvMapping = NULL;
+
+ int rc = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ LogFlow(("pdmR0DevHlp_Mmio2SetUpContext: caller='%s'/%d: returns %Rrc (%p)\n", pDevIns->pReg->szName, pDevIns->iInstance, rc, *ppvMapping));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnPCIPhysRead} */
+static DECLCALLBACK(int) pdmR0DevHlp_PCIPhysRead(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
+ void *pvBuf, size_t cbRead, uint32_t fFlags)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ if (!pPciDev) /* NULL is an alias for the default PCI device. */
+ pPciDev = pDevIns->apPciDevs[0];
+ AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
+ PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
+
+#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
+ /*
+ * Just check the busmaster setting here and forward the request to the generic read helper.
+ */
+ if (PCIDevIsBusmaster(pPciDev))
+ { /* likely */ }
+ else
+ {
+ LogFunc(("caller=%p/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbRead=%#zx\n", pDevIns, pDevIns->iInstance,
+ VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbRead));
+ memset(pvBuf, 0xff, cbRead);
+ return VERR_PDM_NOT_PCI_BUS_MASTER;
+ }
+#endif
+
+ return pDevIns->pHlpR0->pfnPhysRead(pDevIns, GCPhys, pvBuf, cbRead, fFlags);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnPCIPhysWrite} */
+static DECLCALLBACK(int) pdmR0DevHlp_PCIPhysWrite(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, RTGCPHYS GCPhys,
+ const void *pvBuf, size_t cbWrite, uint32_t fFlags)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ if (!pPciDev) /* NULL is an alias for the default PCI device. */
+ pPciDev = pDevIns->apPciDevs[0];
+ AssertReturn(pPciDev, VERR_PDM_NOT_PCI_DEVICE);
+ PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
+
+#ifndef PDM_DO_NOT_RESPECT_PCI_BM_BIT
+ /*
+ * Just check the busmaster setting here and forward the request to the generic read helper.
+ */
+ if (PCIDevIsBusmaster(pPciDev))
+ { /* likely */ }
+ else
+ {
+ LogFunc(("caller=%p/%d: returns %Rrc - Not bus master! GCPhys=%RGp cbWrite=%#zx\n", pDevIns, pDevIns->iInstance,
+ VERR_PDM_NOT_PCI_BUS_MASTER, GCPhys, cbWrite));
+ return VERR_PDM_NOT_PCI_BUS_MASTER;
+ }
+#endif
+
+ return pDevIns->pHlpR0->pfnPhysWrite(pDevIns, GCPhys, pvBuf, cbWrite, fFlags);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnPCISetIrq} */
+static DECLCALLBACK(void) pdmR0DevHlp_PCISetIrq(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, int iIrq, int iLevel)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ if (!pPciDev) /* NULL is an alias for the default PCI device. */
+ pPciDev = pDevIns->apPciDevs[0];
+ AssertReturnVoid(pPciDev);
+ LogFlow(("pdmR0DevHlp_PCISetIrq: caller=%p/%d: pPciDev=%p:{%#x} iIrq=%d iLevel=%d\n",
+ pDevIns, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iIrq, iLevel));
+ PDMPCIDEV_ASSERT_VALID_AND_REGISTERED(pDevIns, pPciDev);
+
+ AssertFailed();
+
+ LogFlow(("pdmR0DevHlp_PCISetIrq: caller=%p/%d: returns void; uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, 0 /*uTagSrc*/));
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnISASetIrq} */
+static DECLCALLBACK(void) pdmR0DevHlp_ISASetIrq(PPDMDEVINS pDevIns, int iIrq, int iLevel)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_ISASetIrq: caller=%p/%d: iIrq=%d iLevel=%d\n", pDevIns, pDevIns->iInstance, iIrq, iLevel));
+
+ AssertFailed();
+
+ LogFlow(("pdmR0DevHlp_ISASetIrq: caller=%p/%d: returns void; uTagSrc=%#x\n", pDevIns, pDevIns->iInstance, 0 /*uTagSrc*/));
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnPhysRead} */
+static DECLCALLBACK(int) pdmR0DevHlp_PhysRead(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, void *pvBuf, size_t cbRead, uint32_t fFlags)
+{
+ RT_NOREF(fFlags);
+
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_PhysRead: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x\n",
+ pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbRead));
+
+ VBOXSTRICTRC rcStrict = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ Log(("pdmR0DevHlp_PhysRead: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
+ return VBOXSTRICTRC_VAL(rcStrict);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnPhysWrite} */
+static DECLCALLBACK(int) pdmR0DevHlp_PhysWrite(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, const void *pvBuf, size_t cbWrite, uint32_t fFlags)
+{
+ RT_NOREF(fFlags);
+
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_PhysWrite: caller=%p/%d: GCPhys=%RGp pvBuf=%p cbWrite=%#x\n",
+ pDevIns, pDevIns->iInstance, GCPhys, pvBuf, cbWrite));
+
+ VBOXSTRICTRC rcStrict = VERR_NOT_IMPLEMENTED;
+ AssertFailed();
+
+ Log(("pdmR0DevHlp_PhysWrite: caller=%p/%d: returns %Rrc\n", pDevIns, pDevIns->iInstance, VBOXSTRICTRC_VAL(rcStrict) ));
+ return VBOXSTRICTRC_VAL(rcStrict);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnA20IsEnabled} */
+static DECLCALLBACK(bool) pdmR0DevHlp_A20IsEnabled(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_A20IsEnabled: caller=%p/%d:\n", pDevIns, pDevIns->iInstance));
+
+ bool fEnabled = false;
+ AssertFailed();
+
+ Log(("pdmR0DevHlp_A20IsEnabled: caller=%p/%d: returns %RTbool\n", pDevIns, pDevIns->iInstance, fEnabled));
+ return fEnabled;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnVMState} */
+static DECLCALLBACK(VMSTATE) pdmR0DevHlp_VMState(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ VMSTATE enmVMState = VMSTATE_CREATING;// pDevIns->Internal.s.pGVM->enmVMState;
+
+ LogFlow(("pdmR0DevHlp_VMState: caller=%p/%d: returns %d\n", pDevIns, pDevIns->iInstance, enmVMState));
+ return enmVMState;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnGetVM} */
+static DECLCALLBACK(PVMCC) pdmR0DevHlp_GetVM(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_GetVM: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
+ AssertFailed();
+ return NULL; //pDevIns->Internal.s.pGVM;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnGetVMCPU} */
+static DECLCALLBACK(PVMCPUCC) pdmR0DevHlp_GetVMCPU(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_GetVMCPU: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
+ AssertFailed();
+ return NULL; //VMMGetCpu(pDevIns->Internal.s.pGVM);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPRC,pfnGetCurrentCpuId} */
+static DECLCALLBACK(VMCPUID) pdmR0DevHlp_GetCurrentCpuId(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_GetCurrentCpuId: caller='%p'/%d for CPU %u\n", pDevIns, pDevIns->iInstance, 0 /*idCpu*/));
+ AssertFailed();
+ return 0; //idCpu;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnGetMainExecutionEngine} */
+static DECLCALLBACK(uint8_t) pdmR0DevHlp_GetMainExecutionEngine(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_GetMainExecutionEngine: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
+ return VM_EXEC_ENGINE_NOT_SET;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerFromMicro} */
+static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerFromMicro(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicroSecs)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return 0; //TMTimerFromMicro(pDevIns->Internal.s.pGVM, hTimer, cMicroSecs);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerFromMilli} */
+static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerFromMilli(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliSecs)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return 0;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerFromNano} */
+static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerFromNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanoSecs)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return 0;
+}
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerGet} */
+static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerGet(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return 0;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerGetFreq} */
+static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerGetFreq(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return 0;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerGetNano} */
+static DECLCALLBACK(uint64_t) pdmR0DevHlp_TimerGetNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return 0;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerIsActive} */
+static DECLCALLBACK(bool) pdmR0DevHlp_TimerIsActive(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return false;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerIsLockOwner} */
+static DECLCALLBACK(bool) pdmR0DevHlp_TimerIsLockOwner(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return false;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerLockClock} */
+static DECLCALLBACK(VBOXSTRICTRC) pdmR0DevHlp_TimerLockClock(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, int rcBusy)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerLockClock2} */
+static DECLCALLBACK(VBOXSTRICTRC) pdmR0DevHlp_TimerLockClock2(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer,
+ PPDMCRITSECT pCritSect, int rcBusy)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSet} */
+static DECLCALLBACK(int) pdmR0DevHlp_TimerSet(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t uExpire)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSetFrequencyHint} */
+static DECLCALLBACK(int) pdmR0DevHlp_TimerSetFrequencyHint(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint32_t uHz)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSetMicro} */
+static DECLCALLBACK(int) pdmR0DevHlp_TimerSetMicro(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMicrosToNext)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSetMillies} */
+static DECLCALLBACK(int) pdmR0DevHlp_TimerSetMillies(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cMilliesToNext)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSetNano} */
+static DECLCALLBACK(int) pdmR0DevHlp_TimerSetNano(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cNanosToNext)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerSetRelative} */
+static DECLCALLBACK(int) pdmR0DevHlp_TimerSetRelative(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, uint64_t cTicksToNext, uint64_t *pu64Now)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerStop} */
+static DECLCALLBACK(int) pdmR0DevHlp_TimerStop(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerUnlockClock} */
+static DECLCALLBACK(void) pdmR0DevHlp_TimerUnlockClock(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTimerUnlockClock2} */
+static DECLCALLBACK(void) pdmR0DevHlp_TimerUnlockClock2(PPDMDEVINS pDevIns, TMTIMERHANDLE hTimer, PPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTMTimeVirtGet} */
+static DECLCALLBACK(uint64_t) pdmR0DevHlp_TMTimeVirtGet(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_TMTimeVirtGet: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
+ AssertFailed();
+ return 0;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTMTimeVirtGetFreq} */
+static DECLCALLBACK(uint64_t) pdmR0DevHlp_TMTimeVirtGetFreq(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_TMTimeVirtGetFreq: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
+ AssertFailed();
+ return 0;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTMTimeVirtGetNano} */
+static DECLCALLBACK(uint64_t) pdmR0DevHlp_TMTimeVirtGetNano(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_TMTimeVirtGetNano: caller='%p'/%d\n", pDevIns, pDevIns->iInstance));
+ AssertFailed();
+ return 0;
+}
+
+
+/** Converts a queue handle to a ring-0 queue pointer. */
+DECLINLINE(PPDMQUEUE) pdmR0DevHlp_QueueToPtr(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return NULL;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnQueueAlloc} */
+static DECLCALLBACK(PPDMQUEUEITEMCORE) pdmR0DevHlp_QueueAlloc(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
+{
+ AssertFailed();
+ return NULL; //PDMQueueAlloc(pdmR0DevHlp_QueueToPtr(pDevIns, hQueue));
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnQueueInsert} */
+static DECLCALLBACK(void) pdmR0DevHlp_QueueInsert(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue, PPDMQUEUEITEMCORE pItem)
+{
+ AssertFailed();
+ //return PDMQueueInsert(pdmR0DevHlp_QueueToPtr(pDevIns, hQueue), pItem);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnQueueFlushIfNecessary} */
+static DECLCALLBACK(bool) pdmR0DevHlp_QueueFlushIfNecessary(PPDMDEVINS pDevIns, PDMQUEUEHANDLE hQueue)
+{
+ AssertFailed();
+ return false; //PDMQueueFlushIfNecessary(pdmR0DevHlp_QueueToPtr(pDevIns, hQueue));
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnTaskTrigger} */
+static DECLCALLBACK(int) pdmR0DevHlp_TaskTrigger(PPDMDEVINS pDevIns, PDMTASKHANDLE hTask)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_TaskTrigger: caller='%s'/%d: hTask=%RU64\n", pDevIns->pReg->szName, pDevIns->iInstance, hTask));
+
+ AssertFailed();
+ int rc = VERR_NOT_IMPLEMENTED; //PDMTaskTrigger(pDevIns->Internal.s.pGVM, PDMTASKTYPE_DEV, pDevIns->pDevInsForR3, hTask);
+
+ LogFlow(("pdmR0DevHlp_TaskTrigger: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventSignal} */
+static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventSignal(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_SUPSemEventSignal: caller='%s'/%d: hEvent=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEvent));
+
+ AssertFailed();
+ int rc = VERR_NOT_IMPLEMENTED; //SUPSemEventSignal(pDevIns->Internal.s.pGVM->pSession, hEvent);
+
+ LogFlow(("pdmR0DevHlp_SUPSemEventSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventWaitNoResume} */
+static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint32_t cMillies)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: hEvent=%p cNsTimeout=%RU32\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cMillies));
+
+ AssertFailed();
+ int rc = VERR_NOT_IMPLEMENTED; //SUPSemEventWaitNoResume(pDevIns->Internal.s.pGVM->pSession, hEvent, cMillies);
+
+ LogFlow(("pdmR0DevHlp_SUPSemEventWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventWaitNsAbsIntr} */
+static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t uNsTimeout)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: hEvent=%p uNsTimeout=%RU64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hEvent, uNsTimeout));
+
+ AssertFailed();
+ int rc = VERR_NOT_IMPLEMENTED; //SUPSemEventWaitNsAbsIntr(pDevIns->Internal.s.pGVM->pSession, hEvent, uNsTimeout);
+
+ LogFlow(("pdmR0DevHlp_SUPSemEventWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventWaitNsRelIntr} */
+static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENT hEvent, uint64_t cNsTimeout)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: hEvent=%p cNsTimeout=%RU64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hEvent, cNsTimeout));
+
+ AssertFailed();
+ int rc = VERR_NOT_IMPLEMENTED; //SUPSemEventWaitNsRelIntr(pDevIns->Internal.s.pGVM->pSession, hEvent, cNsTimeout);
+
+ LogFlow(("pdmR0DevHlp_SUPSemEventWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventGetResolution} */
+static DECLCALLBACK(uint32_t) pdmR0DevHlp_SUPSemEventGetResolution(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_SUPSemEventGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
+
+ AssertFailed();
+ uint32_t cNsResolution = 0; //SUPSemEventGetResolution(pDevIns->Internal.s.pGVM->pSession);
+
+ LogFlow(("pdmR0DevHlp_SUPSemEventGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
+ return cNsResolution;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiSignal} */
+static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventMultiSignal(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
+
+ AssertFailed();
+ int rc = VERR_NOT_IMPLEMENTED; //SUPSemEventMultiSignal(pDevIns->Internal.s.pGVM->pSession, hEventMulti);
+
+ LogFlow(("pdmR0DevHlp_SUPSemEventMultiSignal: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiReset} */
+static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventMultiReset(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_SUPSemEventMultiReset: caller='%s'/%d: hEventMulti=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti));
+
+ AssertFailed();
+ int rc = VERR_NOT_IMPLEMENTED; //SUPSemEventMultiReset(pDevIns->Internal.s.pGVM->pSession, hEventMulti);
+
+ LogFlow(("pdmR0DevHlp_SUPSemEventMultiReset: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiWaitNoResume} */
+static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventMultiWaitNoResume(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
+ uint32_t cMillies)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: hEventMulti=%p cMillies=%RU32\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cMillies));
+
+ AssertFailed();
+ int rc = VERR_NOT_IMPLEMENTED; //SUPSemEventMultiWaitNoResume(pDevIns->Internal.s.pGVM->pSession, hEventMulti, cMillies);
+
+ LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNoResume: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiWaitNsAbsIntr} */
+static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventMultiWaitNsAbsIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
+ uint64_t uNsTimeout)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: hEventMulti=%p uNsTimeout=%RU64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, uNsTimeout));
+
+ AssertFailed();
+ int rc = VERR_NOT_IMPLEMENTED; //SUPSemEventMultiWaitNsAbsIntr(pDevIns->Internal.s.pGVM->pSession, hEventMulti, uNsTimeout);
+
+ LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNsAbsIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiWaitNsRelIntr} */
+static DECLCALLBACK(int) pdmR0DevHlp_SUPSemEventMultiWaitNsRelIntr(PPDMDEVINS pDevIns, SUPSEMEVENTMULTI hEventMulti,
+ uint64_t cNsTimeout)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: hEventMulti=%p cNsTimeout=%RU64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hEventMulti, cNsTimeout));
+
+ AssertFailed();
+ int rc = VERR_NOT_IMPLEMENTED; //SUPSemEventMultiWaitNsRelIntr(pDevIns->Internal.s.pGVM->pSession, hEventMulti, cNsTimeout);
+
+ LogFlow(("pdmR0DevHlp_SUPSemEventMultiWaitNsRelIntr: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnSUPSemEventMultiGetResolution} */
+static DECLCALLBACK(uint32_t) pdmR0DevHlp_SUPSemEventMultiGetResolution(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
+
+ AssertFailed();
+ uint32_t cNsResolution = 0; //SUPSemEventMultiGetResolution(pDevIns->Internal.s.pGVM->pSession);
+
+ LogFlow(("pdmR0DevHlp_SUPSemEventMultiGetResolution: caller='%s'/%d: returns %u\n", pDevIns->pReg->szName, pDevIns->iInstance, cNsResolution));
+ return cNsResolution;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectGetNop} */
+static DECLCALLBACK(PPDMCRITSECT) pdmR0DevHlp_CritSectGetNop(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ PPDMCRITSECT pCritSect = &pDevIns->Internal.s.pDut->CritSectNop;
+ LogFlow(("pdmR0DevHlp_CritSectGetNop: caller='%s'/%d: return %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
+ return pCritSect;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnSetDeviceCritSect} */
+static DECLCALLBACK(int) pdmR0DevHlp_SetDeviceCritSect(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
+{
+ /*
+ * Validate input.
+ *
+ * Note! We only allow the automatically created default critical section
+ * to be replaced by this API.
+ */
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertPtrReturn(pCritSect, VERR_INVALID_POINTER);
+ LogFlow(("pdmR0DevHlp_SetDeviceCritSect: caller='%s'/%d: pCritSect=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pCritSect));
+ AssertReturn(RTCritSectIsInitialized(&pCritSect->s.CritSect), VERR_INVALID_PARAMETER);
+
+ pDevIns->pCritSectRoR0 = pCritSect;
+
+ LogFlow(("pdmR0DevHlp_SetDeviceCritSect: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectEnter} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectEnter(pDevIns->Internal.s.pGVM, pCritSect, rcBusy);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectEnterDebug} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, int rcBusy, RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectEnterDebug(pDevIns->Internal.s.pGVM, pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectTryEnter} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectTryEnter(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectTryEnter(pDevIns->Internal.s.pGVM, pCritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectTryEnterDebug} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectTryEnterDebug(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectTryEnterDebug(pDevIns->Internal.s.pGVM, pCritSect, uId, RT_SRC_POS_ARGS);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectLeave} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectLeave(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectLeave(pDevIns->Internal.s.pGVM, pCritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectIsOwner} */
+static DECLCALLBACK(bool) pdmR0DevHlp_CritSectIsOwner(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectIsOwner(pDevIns->Internal.s.pGVM, pCritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectIsInitialized} */
+static DECLCALLBACK(bool) pdmR0DevHlp_CritSectIsInitialized(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectIsInitialized(pCritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectHasWaiters} */
+static DECLCALLBACK(bool) pdmR0DevHlp_CritSectHasWaiters(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectHasWaiters(pDevIns->Internal.s.pGVM, pCritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectGetRecursion} */
+static DECLCALLBACK(uint32_t) pdmR0DevHlp_CritSectGetRecursion(PPDMDEVINS pDevIns, PCPDMCRITSECT pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectGetRecursion(pCritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectScheduleExitEvent} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectScheduleExitEvent(PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect,
+ SUPSEMEVENT hEventToSignal)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMHCCritSectScheduleExitEvent(pCritSect, hEventToSignal);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwEnterShared} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectRwEnterShared(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectRwEnterShared(pDevIns->Internal.s.pGVM, pCritSect, rcBusy);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwEnterSharedDebug} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectRwEnterSharedDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy,
+ RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectRwEnterSharedDebug(pDevIns->Internal.s.pGVM, pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
+}
+
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwTryEnterShared} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectRwTryEnterShared(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectRwTryEnterShared(pDevIns->Internal.s.pGVM, pCritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwTryEnterSharedDebug} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectRwTryEnterSharedDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect,
+ RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectRwTryEnterSharedDebug(pDevIns->Internal.s.pGVM, pCritSect, uId, RT_SRC_POS_ARGS);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwLeaveShared} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectRwLeaveShared(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectRwLeaveShared(pDevIns->Internal.s.pGVM, pCritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwEnterExcl} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectRwEnterExcl(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectRwEnterExcl(pDevIns->Internal.s.pGVM, pCritSect, rcBusy);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwEnterExclDebug} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectRwEnterExclDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, int rcBusy,
+ RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectRwEnterExclDebug(pDevIns->Internal.s.pGVM, pCritSect, rcBusy, uId, RT_SRC_POS_ARGS);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwTryEnterExcl} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectRwTryEnterExcl(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectRwTryEnterExcl(pDevIns->Internal.s.pGVM, pCritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwTryEnterExclDebug} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectRwTryEnterExclDebug(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect,
+ RTHCUINTPTR uId, RT_SRC_POS_DECL)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectRwTryEnterExclDebug(pDevIns->Internal.s.pGVM, pCritSect, uId, RT_SRC_POS_ARGS);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwLeaveExcl} */
+static DECLCALLBACK(int) pdmR0DevHlp_CritSectRwLeaveExcl(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED; //PDMCritSectRwLeaveExcl(pDevIns->Internal.s.pGVM, pCritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwIsWriteOwner} */
+static DECLCALLBACK(bool) pdmR0DevHlp_CritSectRwIsWriteOwner(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return false; //PDMCritSectRwIsWriteOwner(pDevIns->Internal.s.pGVM, pCritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwIsReadOwner} */
+static DECLCALLBACK(bool) pdmR0DevHlp_CritSectRwIsReadOwner(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect, bool fWannaHear)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ return false; //PDMCritSectRwIsReadOwner(pDevIns->Internal.s.pGVM, pCritSect, fWannaHear);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwGetWriteRecursion} */
+static DECLCALLBACK(uint32_t) pdmR0DevHlp_CritSectRwGetWriteRecursion(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pDevIns);
+ AssertFailed();
+ return 0; //PDMCritSectRwGetWriteRecursion(pCritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwGetWriterReadRecursion} */
+static DECLCALLBACK(uint32_t) pdmR0DevHlp_CritSectRwGetWriterReadRecursion(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pDevIns);
+ AssertFailed();
+ return 0; //PDMCritSectRwGetWriterReadRecursion(pCritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwGetReadCount} */
+static DECLCALLBACK(uint32_t) pdmR0DevHlp_CritSectRwGetReadCount(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pDevIns);
+ AssertFailed();
+ return 0; //PDMCritSectRwGetReadCount(pCritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnCritSectRwIsInitialized} */
+static DECLCALLBACK(bool) pdmR0DevHlp_CritSectRwIsInitialized(PPDMDEVINS pDevIns, PPDMCRITSECTRW pCritSect)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ RT_NOREF(pDevIns);
+ AssertFailed();
+ return false; //PDMCritSectRwIsInitialized(pCritSect);
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnDBGFTraceBuf} */
+static DECLCALLBACK(RTTRACEBUF) pdmR0DevHlp_DBGFTraceBuf(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ AssertFailed();
+ RTTRACEBUF hTraceBuf = NULL; //pDevIns->Internal.s.pGVM->hTraceBufR0;
+ LogFlow(("pdmR0DevHlp_DBGFTraceBuf: caller='%p'/%d: returns %p\n", pDevIns, pDevIns->iInstance, hTraceBuf));
+ return hTraceBuf;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnPCIBusSetUpContext} */
+static DECLCALLBACK(int) pdmR0DevHlp_PCIBusSetUpContext(PPDMDEVINS pDevIns, PPDMPCIBUSREGR0 pPciBusReg, PCPDMPCIHLPR0 *ppPciHlp)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_PCIBusSetUpContext: caller='%p'/%d: pPciBusReg=%p{.u32Version=%#x, .iBus=%#u, .pfnSetIrq=%p, u32EnvVersion=%#x} ppPciHlp=%p\n",
+ pDevIns, pDevIns->iInstance, pPciBusReg, pPciBusReg->u32Version, pPciBusReg->iBus, pPciBusReg->pfnSetIrq,
+ pPciBusReg->u32EndVersion, ppPciHlp));
+#if 0
+ PGVM pGVM = pDevIns->Internal.s.pGVM;
+
+ /*
+ * Validate input.
+ */
+ AssertPtrReturn(pPciBusReg, VERR_INVALID_POINTER);
+ AssertLogRelMsgReturn(pPciBusReg->u32Version == PDM_PCIBUSREGCC_VERSION,
+ ("%#x vs %#x\n", pPciBusReg->u32Version, PDM_PCIBUSREGCC_VERSION), VERR_VERSION_MISMATCH);
+ AssertPtrReturn(pPciBusReg->pfnSetIrq, VERR_INVALID_POINTER);
+ AssertLogRelMsgReturn(pPciBusReg->u32EndVersion == PDM_PCIBUSREGCC_VERSION,
+ ("%#x vs %#x\n", pPciBusReg->u32EndVersion, PDM_PCIBUSREGCC_VERSION), VERR_VERSION_MISMATCH);
+
+ AssertPtrReturn(ppPciHlp, VERR_INVALID_POINTER);
+
+ VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
+ VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
+
+ /* Check the shared bus data (registered earlier from ring-3): */
+ uint32_t iBus = pPciBusReg->iBus;
+ ASMCompilerBarrier();
+ AssertLogRelMsgReturn(iBus < RT_ELEMENTS(pGVM->pdm.s.aPciBuses), ("iBus=%#x\n", iBus), VERR_OUT_OF_RANGE);
+ PPDMPCIBUS pPciBusShared = &pGVM->pdm.s.aPciBuses[iBus];
+ AssertLogRelMsgReturn(pPciBusShared->iBus == iBus, ("%u vs %u\n", pPciBusShared->iBus, iBus), VERR_INVALID_PARAMETER);
+ AssertLogRelMsgReturn(pPciBusShared->pDevInsR3 == pDevIns->pDevInsForR3,
+ ("%p vs %p (iBus=%u)\n", pPciBusShared->pDevInsR3, pDevIns->pDevInsForR3, iBus), VERR_NOT_OWNER);
+
+ /* Check that the bus isn't already registered in ring-0: */
+ AssertCompile(RT_ELEMENTS(pGVM->pdm.s.aPciBuses) == RT_ELEMENTS(pGVM->pdmr0.s.aPciBuses));
+ PPDMPCIBUSR0 pPciBusR0 = &pGVM->pdmr0.s.aPciBuses[iBus];
+ AssertLogRelMsgReturn(pPciBusR0->pDevInsR0 == NULL,
+ ("%p (caller pDevIns=%p, iBus=%u)\n", pPciBusR0->pDevInsR0, pDevIns, iBus),
+ VERR_ALREADY_EXISTS);
+
+ /*
+ * Do the registering.
+ */
+ pPciBusR0->iBus = iBus;
+ pPciBusR0->uPadding0 = 0xbeefbeef;
+ pPciBusR0->pfnSetIrqR0 = pPciBusReg->pfnSetIrq;
+ pPciBusR0->pDevInsR0 = pDevIns;
+#endif
+
+ AssertFailed();
+ *ppPciHlp = NULL; //&g_pdmR0PciHlp;
+
+ LogFlow(("pdmR0DevHlp_PCIBusSetUpContext: caller='%p'/%d: returns VINF_SUCCESS\n", pDevIns, pDevIns->iInstance));
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnIommuSetUpContext} */
+static DECLCALLBACK(int) pdmR0DevHlp_IommuSetUpContext(PPDMDEVINS pDevIns, PPDMIOMMUREGR0 pIommuReg, PCPDMIOMMUHLPR0 *ppIommuHlp)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_IommuSetUpContext: caller='%p'/%d: pIommuReg=%p{.u32Version=%#x, u32TheEnd=%#x} ppIommuHlp=%p\n",
+ pDevIns, pDevIns->iInstance, pIommuReg, pIommuReg->u32Version, pIommuReg->u32TheEnd, ppIommuHlp));
+#if 0
+ PGVM pGVM = pDevIns->Internal.s.pGVM;
+
+ /*
+ * Validate input.
+ */
+ AssertPtrReturn(pIommuReg, VERR_INVALID_POINTER);
+ AssertLogRelMsgReturn(pIommuReg->u32Version == PDM_IOMMUREGCC_VERSION,
+ ("%#x vs %#x\n", pIommuReg->u32Version, PDM_IOMMUREGCC_VERSION), VERR_VERSION_MISMATCH);
+ AssertPtrReturn(pIommuReg->pfnMemAccess, VERR_INVALID_POINTER);
+ AssertPtrReturn(pIommuReg->pfnMemBulkAccess, VERR_INVALID_POINTER);
+ AssertPtrReturn(pIommuReg->pfnMsiRemap, VERR_INVALID_POINTER);
+ AssertLogRelMsgReturn(pIommuReg->u32TheEnd == PDM_IOMMUREGCC_VERSION,
+ ("%#x vs %#x\n", pIommuReg->u32TheEnd, PDM_IOMMUREGCC_VERSION), VERR_VERSION_MISMATCH);
+
+ AssertPtrReturn(ppIommuHlp, VERR_INVALID_POINTER);
+
+ VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
+ VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
+
+ /* Check the IOMMU shared data (registered earlier from ring-3). */
+ uint32_t const idxIommu = pIommuReg->idxIommu;
+ ASMCompilerBarrier();
+ AssertLogRelMsgReturn(idxIommu < RT_ELEMENTS(pGVM->pdm.s.aIommus), ("idxIommu=%#x\n", idxIommu), VERR_OUT_OF_RANGE);
+ PPDMIOMMUR3 pIommuShared = &pGVM->pdm.s.aIommus[idxIommu];
+ AssertLogRelMsgReturn(pIommuShared->idxIommu == idxIommu, ("%u vs %u\n", pIommuShared->idxIommu, idxIommu), VERR_INVALID_PARAMETER);
+ AssertLogRelMsgReturn(pIommuShared->pDevInsR3 == pDevIns->pDevInsForR3,
+ ("%p vs %p (idxIommu=%u)\n", pIommuShared->pDevInsR3, pDevIns->pDevInsForR3, idxIommu), VERR_NOT_OWNER);
+
+ /* Check that the IOMMU isn't already registered in ring-0. */
+ AssertCompile(RT_ELEMENTS(pGVM->pdm.s.aIommus) == RT_ELEMENTS(pGVM->pdmr0.s.aIommus));
+ PPDMIOMMUR0 pIommuR0 = &pGVM->pdmr0.s.aIommus[idxIommu];
+ AssertLogRelMsgReturn(pIommuR0->pDevInsR0 == NULL,
+ ("%p (caller pDevIns=%p, idxIommu=%u)\n", pIommuR0->pDevInsR0, pDevIns, idxIommu),
+ VERR_ALREADY_EXISTS);
+
+ /*
+ * Register.
+ */
+ pIommuR0->idxIommu = idxIommu;
+ pIommuR0->uPadding0 = 0xdeaddead;
+ pIommuR0->pDevInsR0 = pDevIns;
+ pIommuR0->pfnMemAccess = pIommuReg->pfnMemAccess;
+ pIommuR0->pfnMemBulkAccess = pIommuReg->pfnMemBulkAccess;
+ pIommuR0->pfnMsiRemap = pIommuReg->pfnMsiRemap;
+#endif
+
+ AssertFailed();
+ *ppIommuHlp = NULL; //&g_pdmR0IommuHlp;
+
+ LogFlow(("pdmR0DevHlp_IommuSetUpContext: caller='%p'/%d: returns VINF_SUCCESS\n", pDevIns, pDevIns->iInstance));
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnPICSetUpContext} */
+static DECLCALLBACK(int) pdmR0DevHlp_PICSetUpContext(PPDMDEVINS pDevIns, PPDMPICREG pPicReg, PCPDMPICHLP *ppPicHlp)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_PICSetUpContext: caller='%s'/%d: pPicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnGetInterrupt=%p, .u32TheEnd=%#x } ppPicHlp=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pPicReg, pPicReg->u32Version, pPicReg->pfnSetIrq, pPicReg->pfnGetInterrupt, pPicReg->u32TheEnd, ppPicHlp));
+#if 0
+ PGVM pGVM = pDevIns->Internal.s.pGVM;
+
+ /*
+ * Validate input.
+ */
+ AssertMsgReturn(pPicReg->u32Version == PDM_PICREG_VERSION,
+ ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32Version, PDM_PICREG_VERSION),
+ VERR_VERSION_MISMATCH);
+ AssertPtrReturn(pPicReg->pfnSetIrq, VERR_INVALID_POINTER);
+ AssertPtrReturn(pPicReg->pfnGetInterrupt, VERR_INVALID_POINTER);
+ AssertMsgReturn(pPicReg->u32TheEnd == PDM_PICREG_VERSION,
+ ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pPicReg->u32TheEnd, PDM_PICREG_VERSION),
+ VERR_VERSION_MISMATCH);
+ AssertPtrReturn(ppPicHlp, VERR_INVALID_POINTER);
+
+ VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
+ VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
+
+ /* Check that it's the same device as made the ring-3 registrations: */
+ AssertLogRelMsgReturn(pGVM->pdm.s.Pic.pDevInsR3 == pDevIns->pDevInsForR3,
+ ("%p vs %p\n", pGVM->pdm.s.Pic.pDevInsR3, pDevIns->pDevInsForR3), VERR_NOT_OWNER);
+
+ /* Check that it isn't already registered in ring-0: */
+ AssertLogRelMsgReturn(pGVM->pdm.s.Pic.pDevInsR0 == NULL, ("%p (caller pDevIns=%p)\n", pGVM->pdm.s.Pic.pDevInsR0, pDevIns),
+ VERR_ALREADY_EXISTS);
+
+ /*
+ * Take down the callbacks and instance.
+ */
+ pGVM->pdm.s.Pic.pDevInsR0 = pDevIns;
+ pGVM->pdm.s.Pic.pfnSetIrqR0 = pPicReg->pfnSetIrq;
+ pGVM->pdm.s.Pic.pfnGetInterruptR0 = pPicReg->pfnGetInterrupt;
+#endif
+ Log(("PDM: Registered PIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
+
+ /* set the helper pointer and return. */
+ AssertFailed();
+ *ppPicHlp = NULL; //&g_pdmR0PicHlp;
+ LogFlow(("pdmR0DevHlp_PICSetUpContext: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnApicSetUpContext} */
+static DECLCALLBACK(int) pdmR0DevHlp_ApicSetUpContext(PPDMDEVINS pDevIns)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_ApicSetUpContext: caller='%s'/%d:\n", pDevIns->pReg->szName, pDevIns->iInstance));
+#if 0
+ PGVM pGVM = pDevIns->Internal.s.pGVM;
+
+ /*
+ * Validate input.
+ */
+ VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
+ VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
+
+ /* Check that it's the same device as made the ring-3 registrations: */
+ AssertLogRelMsgReturn(pGVM->pdm.s.Apic.pDevInsR3 == pDevIns->pDevInsForR3,
+ ("%p vs %p\n", pGVM->pdm.s.Apic.pDevInsR3, pDevIns->pDevInsForR3), VERR_NOT_OWNER);
+
+ /* Check that it isn't already registered in ring-0: */
+ AssertLogRelMsgReturn(pGVM->pdm.s.Apic.pDevInsR0 == NULL, ("%p (caller pDevIns=%p)\n", pGVM->pdm.s.Apic.pDevInsR0, pDevIns),
+ VERR_ALREADY_EXISTS);
+
+ /*
+ * Take down the instance.
+ */
+ pGVM->pdm.s.Apic.pDevInsR0 = pDevIns;
+#endif
+ Log(("PDM: Registered APIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
+
+ /* set the helper pointer and return. */
+ LogFlow(("pdmR0DevHlp_ApicSetUpContext: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnIoApicSetUpContext} */
+static DECLCALLBACK(int) pdmR0DevHlp_IoApicSetUpContext(PPDMDEVINS pDevIns, PPDMIOAPICREG pIoApicReg, PCPDMIOAPICHLP *ppIoApicHlp)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_IoApicSetUpContext: caller='%s'/%d: pIoApicReg=%p:{.u32Version=%#x, .pfnSetIrq=%p, .pfnSendMsi=%p, .pfnSetEoi=%p, .u32TheEnd=%#x } ppIoApicHlp=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg, pIoApicReg->u32Version, pIoApicReg->pfnSetIrq, pIoApicReg->pfnSendMsi, pIoApicReg->pfnSetEoi, pIoApicReg->u32TheEnd, ppIoApicHlp));
+#if 0
+ PGVM pGVM = pDevIns->Internal.s.pGVM;
+
+ /*
+ * Validate input.
+ */
+ AssertMsgReturn(pIoApicReg->u32Version == PDM_IOAPICREG_VERSION,
+ ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32Version, PDM_IOAPICREG_VERSION),
+ VERR_VERSION_MISMATCH);
+ AssertPtrReturn(pIoApicReg->pfnSetIrq, VERR_INVALID_POINTER);
+ AssertPtrReturn(pIoApicReg->pfnSendMsi, VERR_INVALID_POINTER);
+ AssertPtrReturn(pIoApicReg->pfnSetEoi, VERR_INVALID_POINTER);
+ AssertMsgReturn(pIoApicReg->u32TheEnd == PDM_IOAPICREG_VERSION,
+ ("%s/%d: u32TheEnd=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pIoApicReg->u32TheEnd, PDM_IOAPICREG_VERSION),
+ VERR_VERSION_MISMATCH);
+ AssertPtrReturn(ppIoApicHlp, VERR_INVALID_POINTER);
+
+ VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
+ VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
+
+ /* Check that it's the same device as made the ring-3 registrations: */
+ AssertLogRelMsgReturn(pGVM->pdm.s.IoApic.pDevInsR3 == pDevIns->pDevInsForR3,
+ ("%p vs %p\n", pGVM->pdm.s.IoApic.pDevInsR3, pDevIns->pDevInsForR3), VERR_NOT_OWNER);
+
+ /* Check that it isn't already registered in ring-0: */
+ AssertLogRelMsgReturn(pGVM->pdm.s.IoApic.pDevInsR0 == NULL, ("%p (caller pDevIns=%p)\n", pGVM->pdm.s.IoApic.pDevInsR0, pDevIns),
+ VERR_ALREADY_EXISTS);
+
+ /*
+ * Take down the callbacks and instance.
+ */
+ pGVM->pdm.s.IoApic.pDevInsR0 = pDevIns;
+ pGVM->pdm.s.IoApic.pfnSetIrqR0 = pIoApicReg->pfnSetIrq;
+ pGVM->pdm.s.IoApic.pfnSendMsiR0 = pIoApicReg->pfnSendMsi;
+ pGVM->pdm.s.IoApic.pfnSetEoiR0 = pIoApicReg->pfnSetEoi;
+#endif
+ Log(("PDM: Registered IOAPIC device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
+
+ /* set the helper pointer and return. */
+ AssertFailed();
+ *ppIoApicHlp = NULL; //&g_pdmR0IoApicHlp;
+ LogFlow(("pdmR0DevHlp_IoApicSetUpContext: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnHpetSetUpContext} */
+static DECLCALLBACK(int) pdmR0DevHlp_HpetSetUpContext(PPDMDEVINS pDevIns, PPDMHPETREG pHpetReg, PCPDMHPETHLPR0 *ppHpetHlp)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_HpetSetUpContext: caller='%s'/%d: pHpetReg=%p:{.u32Version=%#x, } ppHpetHlp=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pHpetReg, pHpetReg->u32Version, ppHpetHlp));
+#if 0
+ PGVM pGVM = pDevIns->Internal.s.pGVM;
+
+ /*
+ * Validate input.
+ */
+ AssertMsgReturn(pHpetReg->u32Version == PDM_HPETREG_VERSION,
+ ("%s/%d: u32Version=%#x expected %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, pHpetReg->u32Version, PDM_HPETREG_VERSION),
+ VERR_VERSION_MISMATCH);
+ AssertPtrReturn(ppHpetHlp, VERR_INVALID_POINTER);
+
+ VM_ASSERT_STATE_RETURN(pGVM, VMSTATE_CREATING, VERR_WRONG_ORDER);
+ VM_ASSERT_EMT0_RETURN(pGVM, VERR_VM_THREAD_NOT_EMT);
+
+ /* Check that it's the same device as made the ring-3 registrations: */
+ AssertLogRelMsgReturn(pGVM->pdm.s.pHpet == pDevIns->pDevInsForR3, ("%p vs %p\n", pGVM->pdm.s.pHpet, pDevIns->pDevInsForR3),
+ VERR_NOT_OWNER);
+
+ ///* Check that it isn't already registered in ring-0: */
+ //AssertLogRelMsgReturn(pGVM->pdm.s.Hpet.pDevInsR0 == NULL, ("%p (caller pDevIns=%p)\n", pGVM->pdm.s.Hpet.pDevInsR0, pDevIns),
+ // VERR_ALREADY_EXISTS);
+#endif
+ /*
+ * Nothing to take down here at present.
+ */
+ Log(("PDM: Registered HPET device '%s'/%d pDevIns=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pDevIns));
+
+ /* set the helper pointer and return. */
+ AssertFailed();
+ *ppHpetHlp = NULL; //&g_pdmR0HpetHlp;
+ LogFlow(("pdmR0DevHlp_HpetSetUpContext: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, VINF_SUCCESS));
+ return VINF_SUCCESS;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnPGMHandlerPhysicalPageTempOff} */
+static DECLCALLBACK(int) pdmR0DevHlp_PGMHandlerPhysicalPageTempOff(PPDMDEVINS pDevIns, RTGCPHYS GCPhys, RTGCPHYS GCPhysPage)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_PGMHandlerPhysicalPageTempOff: caller='%s'/%d: GCPhys=%RGp\n", pDevIns->pReg->szName, pDevIns->iInstance, GCPhys));
+
+ AssertFailed();
+ int rc = VERR_NOT_IMPLEMENTED; //PGMHandlerPhysicalPageTempOff(pDevIns->Internal.s.pGVM, GCPhys, GCPhysPage);
+
+ Log(("pdmR0DevHlp_PGMHandlerPhysicalPageTempOff: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnMmioMapMmio2Page} */
+static DECLCALLBACK(int) pdmR0DevHlp_MmioMapMmio2Page(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion, RTGCPHYS offRegion,
+ uint64_t hMmio2, RTGCPHYS offMmio2, uint64_t fPageFlags)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_MmioMapMmio2Page: caller='%s'/%d: hRegion=%RX64 offRegion=%RGp hMmio2=%RX64 offMmio2=%RGp fPageFlags=%RX64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hRegion, offRegion, hMmio2, offMmio2, fPageFlags));
+
+ AssertFailed();
+ int rc = VERR_NOT_IMPLEMENTED; //IOMMmioMapMmio2Page(pDevIns->Internal.s.pGVM, pDevIns, hRegion, offRegion, hMmio2, offMmio2, fPageFlags);
+
+ Log(("pdmR0DevHlp_MmioMapMmio2Page: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnMmioResetRegion} */
+static DECLCALLBACK(int) pdmR0DevHlp_MmioResetRegion(PPDMDEVINS pDevIns, IOMMMIOHANDLE hRegion)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+ LogFlow(("pdmR0DevHlp_MmioResetRegion: caller='%s'/%d: hRegion=%RX64\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, hRegion));
+
+ AssertFailed();
+ int rc = VERR_NOT_IMPLEMENTED; //IOMMmioResetRegion(pDevIns->Internal.s.pGVM, pDevIns, hRegion);
+
+ Log(("pdmR0DevHlp_MmioResetRegion: caller='%s'/%d: returns %Rrc\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, rc));
+ return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLPR0,pfnGIMGetMmio2Regions} */
+static DECLCALLBACK(PGIMMMIO2REGION) pdmR0DevHlp_GIMGetMmio2Regions(PPDMDEVINS pDevIns, uint32_t *pcRegions)
+{
+ PDMDEV_ASSERT_DEVINS(pDevIns);
+
+ LogFlow(("pdmR0DevHlp_GIMGetMmio2Regions: caller='%s'/%d: pcRegions=%p\n",
+ pDevIns->pReg->szName, pDevIns->iInstance, pcRegions));
+
+ AssertFailed();
+ PGIMMMIO2REGION pRegion = NULL; //GIMGetMmio2Regions(pDevIns->Internal.s.pGVM, pcRegions);
+
+ LogFlow(("pdmR0DevHlp_GIMGetMmio2Regions: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pRegion));
+ return pRegion;
+}
+
+
+/**
+ * The Ring-0 Device Helper Callbacks.
+ */
+const PDMDEVHLPR0 g_tstDevPdmDevHlpR0 =
+{
+ PDM_DEVHLPR0_VERSION,
+ pdmR0DevHlp_IoPortSetUpContextEx,
+ pdmR0DevHlp_MmioSetUpContextEx,
+ pdmR0DevHlp_Mmio2SetUpContext,
+ pdmR0DevHlp_PCIPhysRead,
+ pdmR0DevHlp_PCIPhysWrite,
+ pdmR0DevHlp_PCISetIrq,
+ pdmR0DevHlp_ISASetIrq,
+ pdmR0DevHlp_PhysRead,
+ pdmR0DevHlp_PhysWrite,
+ pdmR0DevHlp_A20IsEnabled,
+ pdmR0DevHlp_VMState,
+ pdmR0DevHlp_GetVM,
+ pdmR0DevHlp_GetVMCPU,
+ pdmR0DevHlp_GetCurrentCpuId,
+ pdmR0DevHlp_GetMainExecutionEngine,
+ pdmR0DevHlp_TimerFromMicro,
+ pdmR0DevHlp_TimerFromMilli,
+ pdmR0DevHlp_TimerFromNano,
+ pdmR0DevHlp_TimerGet,
+ pdmR0DevHlp_TimerGetFreq,
+ pdmR0DevHlp_TimerGetNano,
+ pdmR0DevHlp_TimerIsActive,
+ pdmR0DevHlp_TimerIsLockOwner,
+ pdmR0DevHlp_TimerLockClock,
+ pdmR0DevHlp_TimerLockClock2,
+ pdmR0DevHlp_TimerSet,
+ pdmR0DevHlp_TimerSetFrequencyHint,
+ pdmR0DevHlp_TimerSetMicro,
+ pdmR0DevHlp_TimerSetMillies,
+ pdmR0DevHlp_TimerSetNano,
+ pdmR0DevHlp_TimerSetRelative,
+ pdmR0DevHlp_TimerStop,
+ pdmR0DevHlp_TimerUnlockClock,
+ pdmR0DevHlp_TimerUnlockClock2,
+ pdmR0DevHlp_TMTimeVirtGet,
+ pdmR0DevHlp_TMTimeVirtGetFreq,
+ pdmR0DevHlp_TMTimeVirtGetNano,
+ pdmR0DevHlp_QueueAlloc,
+ pdmR0DevHlp_QueueInsert,
+ pdmR0DevHlp_QueueFlushIfNecessary,
+ pdmR0DevHlp_TaskTrigger,
+ pdmR0DevHlp_SUPSemEventSignal,
+ pdmR0DevHlp_SUPSemEventWaitNoResume,
+ pdmR0DevHlp_SUPSemEventWaitNsAbsIntr,
+ pdmR0DevHlp_SUPSemEventWaitNsRelIntr,
+ pdmR0DevHlp_SUPSemEventGetResolution,
+ pdmR0DevHlp_SUPSemEventMultiSignal,
+ pdmR0DevHlp_SUPSemEventMultiReset,
+ pdmR0DevHlp_SUPSemEventMultiWaitNoResume,
+ pdmR0DevHlp_SUPSemEventMultiWaitNsAbsIntr,
+ pdmR0DevHlp_SUPSemEventMultiWaitNsRelIntr,
+ pdmR0DevHlp_SUPSemEventMultiGetResolution,
+ pdmR0DevHlp_CritSectGetNop,
+ pdmR0DevHlp_SetDeviceCritSect,
+ pdmR0DevHlp_CritSectEnter,
+ pdmR0DevHlp_CritSectEnterDebug,
+ pdmR0DevHlp_CritSectTryEnter,
+ pdmR0DevHlp_CritSectTryEnterDebug,
+ pdmR0DevHlp_CritSectLeave,
+ pdmR0DevHlp_CritSectIsOwner,
+ pdmR0DevHlp_CritSectIsInitialized,
+ pdmR0DevHlp_CritSectHasWaiters,
+ pdmR0DevHlp_CritSectGetRecursion,
+ pdmR0DevHlp_CritSectScheduleExitEvent,
+ pdmR0DevHlp_CritSectRwEnterShared,
+ pdmR0DevHlp_CritSectRwEnterSharedDebug,
+ pdmR0DevHlp_CritSectRwTryEnterShared,
+ pdmR0DevHlp_CritSectRwTryEnterSharedDebug,
+ pdmR0DevHlp_CritSectRwLeaveShared,
+ pdmR0DevHlp_CritSectRwEnterExcl,
+ pdmR0DevHlp_CritSectRwEnterExclDebug,
+ pdmR0DevHlp_CritSectRwTryEnterExcl,
+ pdmR0DevHlp_CritSectRwTryEnterExclDebug,
+ pdmR0DevHlp_CritSectRwLeaveExcl,
+ pdmR0DevHlp_CritSectRwIsWriteOwner,
+ pdmR0DevHlp_CritSectRwIsReadOwner,
+ pdmR0DevHlp_CritSectRwGetWriteRecursion,
+ pdmR0DevHlp_CritSectRwGetWriterReadRecursion,
+ pdmR0DevHlp_CritSectRwGetReadCount,
+ pdmR0DevHlp_CritSectRwIsInitialized,
+ pdmR0DevHlp_DBGFTraceBuf,
+ pdmR0DevHlp_PCIBusSetUpContext,
+ pdmR0DevHlp_IommuSetUpContext,
+ pdmR0DevHlp_PICSetUpContext,
+ pdmR0DevHlp_ApicSetUpContext,
+ pdmR0DevHlp_IoApicSetUpContext,
+ pdmR0DevHlp_HpetSetUpContext,
+ pdmR0DevHlp_PGMHandlerPhysicalPageTempOff,
+ pdmR0DevHlp_MmioMapMmio2Page,
+ pdmR0DevHlp_MmioResetRegion,
+ pdmR0DevHlp_GIMGetMmio2Regions,
+ NULL /*pfnReserved1*/,
+ NULL /*pfnReserved2*/,
+ NULL /*pfnReserved3*/,
+ NULL /*pfnReserved4*/,
+ NULL /*pfnReserved5*/,
+ NULL /*pfnReserved6*/,
+ NULL /*pfnReserved7*/,
+ NULL /*pfnReserved8*/,
+ NULL /*pfnReserved9*/,
+ NULL /*pfnReserved10*/,
+ PDM_DEVHLPR0_VERSION
+};
diff --git a/src/VBox/Devices/testcase/tstDevicePdmThread.cpp b/src/VBox/Devices/testcase/tstDevicePdmThread.cpp
new file mode 100644
index 00000000..1e218e53
--- /dev/null
+++ b/src/VBox/Devices/testcase/tstDevicePdmThread.cpp
@@ -0,0 +1,996 @@
+/* $Id: tstDevicePdmThread.cpp $ */
+/** @file
+ * PDM Thread - Thread Management (copied from PDMThread).
+ */
+
+/*
+ * Copyright (C) 2007-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+/// @todo \#define LOG_GROUP LOG_GROUP_PDM_THREAD
+#include <VBox/err.h>
+#include <VBox/log.h>
+
+#include <iprt/asm.h>
+#include <iprt/semaphore.h>
+#include <iprt/assert.h>
+#include <iprt/mem.h>
+#include <iprt/thread.h>
+
+#include "tstDeviceInternal.h"
+
+
+/*********************************************************************************************************************************
+* Internal Functions *
+*********************************************************************************************************************************/
+static DECLCALLBACK(int) pdmR3ThreadMain(RTTHREAD Thread, void *pvUser);
+
+
+/**
+ * Wrapper around ASMAtomicCmpXchgSize.
+ */
+DECLINLINE(bool) pdmR3AtomicCmpXchgState(PPDMTHREAD pThread, PDMTHREADSTATE enmNewState, PDMTHREADSTATE enmOldState)
+{
+ bool fRc;
+ ASMAtomicCmpXchgSize(&pThread->enmState, enmNewState, enmOldState, fRc);
+ return fRc;
+}
+
+
+/**
+ * Does the wakeup call.
+ *
+ * @returns VBox status code. Already asserted on failure.
+ * @param pThread The PDM thread.
+ */
+static DECLCALLBACK(int) pdmR3ThreadWakeUp(PPDMTHREAD pThread)
+{
+ RTSemEventMultiSignal(pThread->Internal.s.SleepEvent);
+
+ int rc;
+ switch (pThread->Internal.s.enmType)
+ {
+ case PDMTHREADTYPE_DEVICE:
+ rc = pThread->u.Dev.pfnWakeUp(pThread->u.Dev.pDevIns, pThread);
+ break;
+
+ case PDMTHREADTYPE_USB:
+ rc = pThread->u.Usb.pfnWakeUp(pThread->u.Usb.pUsbIns, pThread);
+ break;
+
+ case PDMTHREADTYPE_DRIVER:
+ rc = pThread->u.Drv.pfnWakeUp(pThread->u.Drv.pDrvIns, pThread);
+ break;
+
+ case PDMTHREADTYPE_INTERNAL:
+ rc = pThread->u.Int.pfnWakeUp(NULL /*pVM*/, pThread);
+ break;
+
+ case PDMTHREADTYPE_EXTERNAL:
+ rc = pThread->u.Ext.pfnWakeUp(pThread);
+ break;
+
+ default:
+ AssertMsgFailed(("%d\n", pThread->Internal.s.enmType));
+ rc = VERR_PDM_THREAD_IPE_1;
+ break;
+ }
+ AssertRC(rc);
+ return rc;
+}
+
+
+/**
+ * Allocates new thread instance.
+ *
+ * @returns VBox status code.
+ * @param pDut The device under test.
+ * @param ppThread Where to store the pointer to the instance.
+ */
+static int pdmR3ThreadNew(PTSTDEVDUTINT pDut, PPPDMTHREAD ppThread)
+{
+ PPDMTHREAD pThread = (PPDMTHREAD)RTMemAllocZ(sizeof(*pThread));
+ if (!pThread)
+ return VERR_NO_MEMORY;
+
+ pThread->u32Version = PDMTHREAD_VERSION;
+ pThread->enmState = PDMTHREADSTATE_INITIALIZING;
+ pThread->Thread = NIL_RTTHREAD;
+ pThread->Internal.s.pDut = pDut;
+
+ *ppThread = pThread;
+ return VINF_SUCCESS;
+}
+
+
+
+/**
+ * Initialize a new thread, this actually creates the thread.
+ *
+ * @returns VBox status code.
+ * @param pDut The device under test.
+ * @param ppThread Where the thread instance data handle is.
+ * @param cbStack The stack size, see RTThreadCreate().
+ * @param enmType The thread type, see RTThreadCreate().
+ * @param pszName The thread name, see RTThreadCreate().
+ */
+static int pdmR3ThreadInit(PTSTDEVDUTINT pDut, PPPDMTHREAD ppThread, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
+{
+ PPDMTHREAD pThread = *ppThread;
+
+ int rc = RTSemEventMultiCreate(&pThread->Internal.s.BlockEvent);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTSemEventMultiCreate(&pThread->Internal.s.SleepEvent);
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * Create the thread and wait for it to initialize.
+ * The newly created thread will set the PDMTHREAD::Thread member.
+ */
+ RTTHREAD Thread;
+ rc = RTThreadCreate(&Thread, pdmR3ThreadMain, pThread, cbStack, enmType, RTTHREADFLAGS_WAITABLE, pszName);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTThreadUserWait(Thread, 60*1000);
+ if ( RT_SUCCESS(rc)
+ && pThread->enmState != PDMTHREADSTATE_SUSPENDED)
+ rc = VERR_PDM_THREAD_IPE_2;
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * Insert it into the thread list.
+ */
+ tstDevDutLockExcl(pDut);
+ RTListAppend(&pDut->LstPdmThreads, &pThread->Internal.s.NdPdmThrds);
+ tstDevDutUnlockExcl(pDut);
+
+ rc = RTThreadUserReset(Thread);
+ AssertRC(rc);
+ return rc;
+ }
+
+ /* bailout */
+ RTThreadWait(Thread, 60*1000, NULL);
+ }
+ RTSemEventMultiDestroy(pThread->Internal.s.SleepEvent);
+ pThread->Internal.s.SleepEvent = NIL_RTSEMEVENTMULTI;
+ }
+ RTSemEventMultiDestroy(pThread->Internal.s.BlockEvent);
+ pThread->Internal.s.BlockEvent = NIL_RTSEMEVENTMULTI;
+ }
+ RTMemFree(pThread);
+ *ppThread = NULL;
+
+ return rc;
+}
+
+
+/**
+ * Device Helper for creating a thread associated with a device.
+ *
+ * @returns VBox status code.
+ * @param pDut The device under test.
+ * @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.
+ */
+DECLHIDDEN(int) tstDevPdmR3ThreadCreateDevice(PTSTDEVDUTINT pDut, PPDMDEVINS pDevIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDEV pfnThread,
+ PFNPDMTHREADWAKEUPDEV pfnWakeUp, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
+{
+ int rc = pdmR3ThreadNew(pDut, ppThread);
+ if (RT_SUCCESS(rc))
+ {
+ PPDMTHREAD pThread = *ppThread;
+ pThread->pvUser = pvUser;
+ pThread->Internal.s.enmType = PDMTHREADTYPE_DEVICE;
+ pThread->u.Dev.pDevIns = pDevIns;
+ pThread->u.Dev.pfnThread = pfnThread;
+ pThread->u.Dev.pfnWakeUp = pfnWakeUp;
+ rc = pdmR3ThreadInit(pDut, ppThread, cbStack, enmType, pszName);
+ }
+ return rc;
+}
+
+
+/**
+ * USB Device Helper for creating a thread associated with an USB device.
+ *
+ * @returns VBox status code.
+ * @param pDut The device under test.
+ * @param pUsbIns The USB 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.
+ */
+DECLHIDDEN(int) tstDevPdmR3ThreadCreateUsb(PTSTDEVDUTINT pDut, PPDMUSBINS pUsbIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADUSB pfnThread,
+ PFNPDMTHREADWAKEUPUSB pfnWakeUp, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
+{
+ int rc = pdmR3ThreadNew(pDut, ppThread);
+ if (RT_SUCCESS(rc))
+ {
+ PPDMTHREAD pThread = *ppThread;
+ pThread->pvUser = pvUser;
+ pThread->Internal.s.enmType = PDMTHREADTYPE_USB;
+ pThread->u.Usb.pUsbIns = pUsbIns;
+ pThread->u.Usb.pfnThread = pfnThread;
+ pThread->u.Usb.pfnWakeUp = pfnWakeUp;
+ rc = pdmR3ThreadInit(pDut, ppThread, cbStack, enmType, pszName);
+ }
+ return rc;
+}
+
+
+/**
+ * Driver Helper for creating a thread associated with a driver.
+ *
+ * @returns VBox status code.
+ * @param pDut The device under test.
+ * @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.
+ */
+DECLHIDDEN(int) tstDevPdmR3ThreadCreateDriver(PTSTDEVDUTINT pDut, PPDMDRVINS pDrvIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDRV pfnThread,
+ PFNPDMTHREADWAKEUPDRV pfnWakeUp, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
+{
+ int rc = pdmR3ThreadNew(pDut, ppThread);
+ if (RT_SUCCESS(rc))
+ {
+ PPDMTHREAD pThread = *ppThread;
+ pThread->pvUser = pvUser;
+ pThread->Internal.s.enmType = PDMTHREADTYPE_DRIVER;
+ pThread->u.Drv.pDrvIns = pDrvIns;
+ pThread->u.Drv.pfnThread = pfnThread;
+ pThread->u.Drv.pfnWakeUp = pfnWakeUp;
+ rc = pdmR3ThreadInit(pDut, ppThread, cbStack, enmType, pszName);
+ }
+ return rc;
+}
+
+
+/**
+ * Creates a PDM thread for internal use in the VM.
+ *
+ * @returns VBox status code.
+ * @param pDut The device under test.
+ * @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.
+ */
+DECLHIDDEN(int) tstDevPdmR3ThreadCreate(PTSTDEVDUTINT pDut, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADINT pfnThread,
+ PFNPDMTHREADWAKEUPINT pfnWakeUp, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
+{
+ int rc = pdmR3ThreadNew(pDut, ppThread);
+ if (RT_SUCCESS(rc))
+ {
+ PPDMTHREAD pThread = *ppThread;
+ pThread->pvUser = pvUser;
+ pThread->Internal.s.enmType = PDMTHREADTYPE_INTERNAL;
+ pThread->u.Int.pfnThread = pfnThread;
+ pThread->u.Int.pfnWakeUp = pfnWakeUp;
+ rc = pdmR3ThreadInit(pDut, ppThread, cbStack, enmType, pszName);
+ }
+ return rc;
+}
+
+
+/**
+ * Creates a PDM thread for VM use by some external party.
+ *
+ * @returns VBox status code.
+ * @param pDut The device under test.
+ * @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.
+ */
+DECLHIDDEN(int) tstDevPdmR3ThreadCreateExternal(PTSTDEVDUTINT pDut, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADEXT pfnThread,
+ PFNPDMTHREADWAKEUPEXT pfnWakeUp, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
+{
+ int rc = pdmR3ThreadNew(pDut, ppThread);
+ if (RT_SUCCESS(rc))
+ {
+ PPDMTHREAD pThread = *ppThread;
+ pThread->pvUser = pvUser;
+ pThread->Internal.s.enmType = PDMTHREADTYPE_EXTERNAL;
+ pThread->u.Ext.pfnThread = pfnThread;
+ pThread->u.Ext.pfnWakeUp = pfnWakeUp;
+ rc = pdmR3ThreadInit(pDut, ppThread, cbStack, enmType, pszName);
+ }
+ return rc;
+}
+
+
+/**
+ * Destroys a PDM thread.
+ *
+ * This will wakeup the thread, tell it to terminate, and wait for it terminate.
+ *
+ * @returns VBox status code.
+ * This reflects the success off destroying the thread and not the exit code
+ * of the thread as this is stored in *pRcThread.
+ * @param pThread The thread to destroy.
+ * @param pRcThread Where to store the thread exit code. Optional.
+ * @thread The emulation thread (EMT).
+ */
+DECLHIDDEN(int) tstDevPdmR3ThreadDestroy(PPDMTHREAD pThread, int *pRcThread)
+{
+ /*
+ * Assert sanity.
+ */
+ AssertPtrReturn(pThread, VERR_INVALID_POINTER);
+ AssertReturn(pThread->u32Version == PDMTHREAD_VERSION, VERR_INVALID_MAGIC);
+ Assert(pThread->Thread != RTThreadSelf());
+ AssertPtrNullReturn(pRcThread, VERR_INVALID_POINTER);
+
+ PTSTDEVDUTINT pDut = pThread->Internal.s.pDut;
+
+ /*
+ * Advance the thread to the terminating state.
+ */
+ int rc = VINF_SUCCESS;
+ if (pThread->enmState <= PDMTHREADSTATE_TERMINATING)
+ {
+ for (;;)
+ {
+ PDMTHREADSTATE enmState = pThread->enmState;
+ switch (enmState)
+ {
+ case PDMTHREADSTATE_RUNNING:
+ if (!pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_TERMINATING, enmState))
+ continue;
+ rc = pdmR3ThreadWakeUp(pThread);
+ break;
+
+ case PDMTHREADSTATE_SUSPENDED:
+ case PDMTHREADSTATE_SUSPENDING:
+ case PDMTHREADSTATE_RESUMING:
+ case PDMTHREADSTATE_INITIALIZING:
+ if (!pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_TERMINATING, enmState))
+ continue;
+ break;
+
+ case PDMTHREADSTATE_TERMINATING:
+ case PDMTHREADSTATE_TERMINATED:
+ break;
+
+ default:
+ AssertMsgFailed(("enmState=%d\n", enmState));
+ rc = VERR_PDM_THREAD_IPE_2;
+ break;
+ }
+ break;
+ }
+ }
+ int rc2 = RTSemEventMultiSignal(pThread->Internal.s.BlockEvent);
+ AssertRC(rc2);
+
+ /*
+ * Wait for it to terminate and the do cleanups.
+ */
+ rc2 = RTThreadWait(pThread->Thread, RT_SUCCESS(rc) ? 60*1000 : 150, pRcThread);
+ if (RT_SUCCESS(rc2))
+ {
+ /* make it invalid. */
+ pThread->u32Version = 0xffffffff;
+ pThread->enmState = PDMTHREADSTATE_INVALID;
+ pThread->Thread = NIL_RTTHREAD;
+
+ /* unlink */
+ tstDevDutLockExcl(pDut);
+ RTListNodeRemove(&pThread->Internal.s.NdPdmThrds);
+ tstDevDutUnlockExcl(pDut);
+
+ /* free the resources */
+ RTSemEventMultiDestroy(pThread->Internal.s.BlockEvent);
+ pThread->Internal.s.BlockEvent = NIL_RTSEMEVENTMULTI;
+
+ RTSemEventMultiDestroy(pThread->Internal.s.SleepEvent);
+ pThread->Internal.s.SleepEvent = NIL_RTSEMEVENTMULTI;
+
+ RTMemFree(pThread);
+ }
+ else if (RT_SUCCESS(rc))
+ rc = rc2;
+
+ return rc;
+}
+
+
+/**
+ * Destroys all threads associated with a device.
+ *
+ * This function is called by PDMDevice when a device is
+ * destroyed (not currently implemented).
+ *
+ * @returns VBox status code of the first failure.
+ * @param pDut The device under test.
+ * @param pDevIns the device instance.
+ */
+DECLHIDDEN(int) tstDevPdmR3ThreadDestroyDevice(PTSTDEVDUTINT pDut, PPDMDEVINS pDevIns)
+{
+ int rc = VINF_SUCCESS;
+
+ AssertPtr(pDevIns);
+
+ tstDevDutLockExcl(pDut);
+#if 0
+ PPDMTHREAD pThread = pUVM->pdm.s.pThreads;
+ while (pThread)
+ {
+ PPDMTHREAD pNext = pThread->Internal.s.pNext;
+ if ( pThread->Internal.s.enmType == PDMTHREADTYPE_DEVICE
+ && pThread->u.Dev.pDevIns == pDevIns)
+ {
+ int rc2 = PDMR3ThreadDestroy(pThread, NULL);
+ if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
+ rc = rc2;
+ }
+ pThread = pNext;
+ }
+#endif
+ tstDevDutUnlockExcl(pDut);
+ return rc;
+}
+
+
+/**
+ * Destroys all threads associated with an USB device.
+ *
+ * This function is called by PDMUsb when a device is destroyed.
+ *
+ * @returns VBox status code of the first failure.
+ * @param pDut The device under test.
+ * @param pUsbIns The USB device instance.
+ */
+DECLHIDDEN(int) tstDevPdmR3ThreadDestroyUsb(PTSTDEVDUTINT pDut, PPDMUSBINS pUsbIns)
+{
+ int rc = VINF_SUCCESS;
+
+ AssertPtr(pUsbIns);
+
+ tstDevDutLockExcl(pDut);
+#if 0
+ PPDMTHREAD pThread = pUVM->pdm.s.pThreads;
+ while (pThread)
+ {
+ PPDMTHREAD pNext = pThread->Internal.s.pNext;
+ if ( pThread->Internal.s.enmType == PDMTHREADTYPE_DEVICE
+ && pThread->u.Usb.pUsbIns == pUsbIns)
+ {
+ int rc2 = PDMR3ThreadDestroy(pThread, NULL);
+ if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
+ rc = rc2;
+ }
+ pThread = pNext;
+ }
+#endif
+ tstDevDutUnlockExcl(pDut);
+ return rc;
+}
+
+
+/**
+ * Destroys all threads associated with a driver.
+ *
+ * This function is called by PDMDriver when a driver is destroyed.
+ *
+ * @returns VBox status code of the first failure.
+ * @param pDut The device under test.
+ * @param pDrvIns The driver instance.
+ */
+DECLHIDDEN(int) tstDevPdmR3ThreadDestroyDriver(PTSTDEVDUTINT pDut, PPDMDRVINS pDrvIns)
+{
+ int rc = VINF_SUCCESS;
+
+ AssertPtr(pDrvIns);
+
+ tstDevDutLockExcl(pDut);
+#if 0
+ PPDMTHREAD pThread = pUVM->pdm.s.pThreads;
+ while (pThread)
+ {
+ PPDMTHREAD pNext = pThread->Internal.s.pNext;
+ if ( pThread->Internal.s.enmType == PDMTHREADTYPE_DRIVER
+ && pThread->u.Drv.pDrvIns == pDrvIns)
+ {
+ int rc2 = PDMR3ThreadDestroy(pThread, NULL);
+ if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
+ rc = rc2;
+ }
+ pThread = pNext;
+ }
+#endif
+ tstDevDutUnlockExcl(pDut);
+ return rc;
+}
+
+
+/**
+ * Called For VM power off.
+ *
+ * @param pDut The device under test.
+ */
+DECLHIDDEN(void) tstDevPdmR3ThreadDestroyAll(PTSTDEVDUTINT pDut)
+{
+ tstDevDutLockExcl(pDut);
+#if 0
+ PPDMTHREAD pThread = pUVM->pdm.s.pThreads;
+ while (pThread)
+ {
+ PPDMTHREAD pNext = pThread->Internal.s.pNext;
+ int rc2 = PDMR3ThreadDestroy(pThread, NULL);
+ AssertRC(rc2);
+ pThread = pNext;
+ }
+ Assert(!pUVM->pdm.s.pThreads && !pUVM->pdm.s.pThreadsTail);
+#endif
+ tstDevDutUnlockExcl(pDut);
+}
+
+
+/**
+ * Initiate termination of the thread (self) because something failed in a bad way.
+ *
+ * @param pThread The PDM thread.
+ */
+static void pdmR3ThreadBailMeOut(PPDMTHREAD pThread)
+{
+ for (;;)
+ {
+ PDMTHREADSTATE enmState = pThread->enmState;
+ switch (enmState)
+ {
+ case PDMTHREADSTATE_SUSPENDING:
+ case PDMTHREADSTATE_SUSPENDED:
+ case PDMTHREADSTATE_RESUMING:
+ case PDMTHREADSTATE_RUNNING:
+ if (!pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_TERMINATING, enmState))
+ continue;
+ break;
+
+ case PDMTHREADSTATE_TERMINATING:
+ case PDMTHREADSTATE_TERMINATED:
+ break;
+
+ case PDMTHREADSTATE_INITIALIZING:
+ default:
+ AssertMsgFailed(("enmState=%d\n", enmState));
+ break;
+ }
+ break;
+ }
+}
+
+
+/**
+ * Called by the PDM thread in response to a wakeup call with
+ * suspending as the new state.
+ *
+ * The thread will block in side this call until the state is changed in
+ * response to a VM state change or to the device/driver/whatever calling the
+ * PDMR3ThreadResume API.
+ *
+ * @returns VBox status code.
+ * On failure, terminate the thread.
+ * @param pThread The PDM thread.
+ */
+DECLHIDDEN(int) tstDevPdmR3ThreadIAmSuspending(PPDMTHREAD pThread)
+{
+ /*
+ * Assert sanity.
+ */
+ AssertPtr(pThread);
+ AssertReturn(pThread->u32Version == PDMTHREAD_VERSION, VERR_INVALID_MAGIC);
+ Assert(pThread->Thread == RTThreadSelf() || pThread->enmState == PDMTHREADSTATE_INITIALIZING);
+ PDMTHREADSTATE enmState = pThread->enmState;
+ Assert( enmState == PDMTHREADSTATE_SUSPENDING
+ || enmState == PDMTHREADSTATE_INITIALIZING);
+
+ /*
+ * Update the state, notify the control thread (the API caller) and go to sleep.
+ */
+ int rc = VERR_WRONG_ORDER;
+ if (pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_SUSPENDED, enmState))
+ {
+ rc = RTThreadUserSignal(pThread->Thread);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTSemEventMultiWait(pThread->Internal.s.BlockEvent, RT_INDEFINITE_WAIT);
+ if ( RT_SUCCESS(rc)
+ && pThread->enmState != PDMTHREADSTATE_SUSPENDED)
+ return rc;
+
+ if (RT_SUCCESS(rc))
+ rc = VERR_PDM_THREAD_IPE_2;
+ }
+ }
+
+ AssertMsgFailed(("rc=%d enmState=%d\n", rc, pThread->enmState));
+ pdmR3ThreadBailMeOut(pThread);
+ return rc;
+}
+
+
+/**
+ * Called by the PDM thread in response to a resuming state.
+ *
+ * The purpose of this API is to tell the PDMR3ThreadResume caller that
+ * the PDM thread has successfully resumed. It will also do the
+ * state transition from the resuming to the running state.
+ *
+ * @returns VBox status code.
+ * On failure, terminate the thread.
+ * @param pThread The PDM thread.
+ */
+DECLHIDDEN(int) tstDevPdmR3ThreadIAmRunning(PPDMTHREAD pThread)
+{
+ /*
+ * Assert sanity.
+ */
+ Assert(pThread->enmState == PDMTHREADSTATE_RESUMING);
+ Assert(pThread->Thread == RTThreadSelf());
+
+ /*
+ * Update the state and tell the control thread (the guy calling the resume API).
+ */
+ int rc = VERR_WRONG_ORDER;
+ if (pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_RUNNING, PDMTHREADSTATE_RESUMING))
+ {
+ rc = RTThreadUserSignal(pThread->Thread);
+ if (RT_SUCCESS(rc))
+ return rc;
+ }
+
+ AssertMsgFailed(("rc=%d enmState=%d\n", rc, pThread->enmState));
+ pdmR3ThreadBailMeOut(pThread);
+ return rc;
+}
+
+
+/**
+ * Called by the PDM thread instead of RTThreadSleep.
+ *
+ * The difference is that the sleep will be interrupted on state change. The
+ * thread must be in the running state, otherwise it will return immediately.
+ *
+ * @returns VBox status code.
+ * @retval VINF_SUCCESS on success or state change.
+ * @retval VERR_INTERRUPTED on signal or APC.
+ *
+ * @param pThread The PDM thread.
+ * @param cMillies The number of milliseconds to sleep.
+ */
+DECLHIDDEN(int) tstDevPdmR3ThreadSleep(PPDMTHREAD pThread, RTMSINTERVAL cMillies)
+{
+ /*
+ * Assert sanity.
+ */
+ AssertReturn(pThread->enmState > PDMTHREADSTATE_INVALID && pThread->enmState < PDMTHREADSTATE_TERMINATED, VERR_PDM_THREAD_IPE_2);
+ AssertReturn(pThread->Thread == RTThreadSelf(), VERR_PDM_THREAD_INVALID_CALLER);
+
+ /*
+ * Reset the event semaphore, check the state and sleep.
+ */
+ RTSemEventMultiReset(pThread->Internal.s.SleepEvent);
+ if (pThread->enmState != PDMTHREADSTATE_RUNNING)
+ return VINF_SUCCESS;
+ return RTSemEventMultiWaitNoResume(pThread->Internal.s.SleepEvent, cMillies);
+}
+
+
+/**
+ * The PDM thread function.
+ *
+ * @returns return from pfnThread.
+ *
+ * @param Thread The thread handle.
+ * @param pvUser Pointer to the PDMTHREAD structure.
+ */
+static DECLCALLBACK(int) pdmR3ThreadMain(RTTHREAD Thread, void *pvUser)
+{
+ PPDMTHREAD pThread = (PPDMTHREAD)pvUser;
+ Log(("PDMThread: Initializing thread %RTthrd / %p / '%s'...\n", Thread, pThread, RTThreadGetName(Thread)));
+ pThread->Thread = Thread;
+
+ /*
+ * The run loop.
+ *
+ * It handles simple thread functions which returns when they see a suspending
+ * request and leaves the PDMR3ThreadIAmSuspending and PDMR3ThreadIAmRunning
+ * parts to us.
+ */
+ int rc;
+ for (;;)
+ {
+ switch (pThread->Internal.s.enmType)
+ {
+ case PDMTHREADTYPE_DEVICE:
+ rc = pThread->u.Dev.pfnThread(pThread->u.Dev.pDevIns, pThread);
+ break;
+
+ case PDMTHREADTYPE_USB:
+ rc = pThread->u.Usb.pfnThread(pThread->u.Usb.pUsbIns, pThread);
+ break;
+
+ case PDMTHREADTYPE_DRIVER:
+ rc = pThread->u.Drv.pfnThread(pThread->u.Drv.pDrvIns, pThread);
+ break;
+
+ case PDMTHREADTYPE_INTERNAL:
+ rc = pThread->u.Int.pfnThread(NULL /*pVM*/, pThread);
+ break;
+
+ case PDMTHREADTYPE_EXTERNAL:
+ rc = pThread->u.Ext.pfnThread(pThread);
+ break;
+
+ default:
+ AssertMsgFailed(("%d\n", pThread->Internal.s.enmType));
+ rc = VERR_PDM_THREAD_IPE_1;
+ break;
+ }
+ if (RT_FAILURE(rc))
+ break;
+
+ /*
+ * If this is a simple thread function, the state will be suspending
+ * or initializing now. If it isn't we're supposed to terminate.
+ */
+ if ( pThread->enmState != PDMTHREADSTATE_SUSPENDING
+ && pThread->enmState != PDMTHREADSTATE_INITIALIZING)
+ {
+ Assert(pThread->enmState == PDMTHREADSTATE_TERMINATING);
+ break;
+ }
+ rc = tstDevPdmR3ThreadIAmSuspending(pThread);
+ if (RT_FAILURE(rc))
+ break;
+ if (pThread->enmState != PDMTHREADSTATE_RESUMING)
+ {
+ Assert(pThread->enmState == PDMTHREADSTATE_TERMINATING);
+ break;
+ }
+
+ rc = tstDevPdmR3ThreadIAmRunning(pThread);
+ if (RT_FAILURE(rc))
+ break;
+ }
+
+ if (RT_FAILURE(rc))
+ LogRel(("PDMThread: Thread '%s' (%RTthrd) quit unexpectedly with rc=%Rrc.\n", RTThreadGetName(Thread), Thread, rc));
+
+ /*
+ * Advance the state to terminating and then on to terminated.
+ */
+ for (;;)
+ {
+ PDMTHREADSTATE enmState = pThread->enmState;
+ if ( enmState == PDMTHREADSTATE_TERMINATING
+ || pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_TERMINATING, enmState))
+ break;
+ }
+
+ ASMAtomicXchgSize(&pThread->enmState, PDMTHREADSTATE_TERMINATED);
+ int rc2 = RTThreadUserSignal(Thread); AssertRC(rc2);
+
+ Log(("PDMThread: Terminating thread %RTthrd / %p / '%s': %Rrc\n", Thread, pThread, RTThreadGetName(Thread), rc));
+ return rc;
+}
+
+
+/**
+ * Initiate termination of the thread because something failed in a bad way.
+ *
+ * @param pThread The PDM thread.
+ */
+static void pdmR3ThreadBailOut(PPDMTHREAD pThread)
+{
+ for (;;)
+ {
+ PDMTHREADSTATE enmState = pThread->enmState;
+ switch (enmState)
+ {
+ case PDMTHREADSTATE_SUSPENDING:
+ case PDMTHREADSTATE_SUSPENDED:
+ if (!pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_TERMINATING, enmState))
+ continue;
+ RTSemEventMultiSignal(pThread->Internal.s.BlockEvent);
+ break;
+
+ case PDMTHREADSTATE_RESUMING:
+ if (!pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_TERMINATING, enmState))
+ continue;
+ break;
+
+ case PDMTHREADSTATE_RUNNING:
+ if (!pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_TERMINATING, enmState))
+ continue;
+ pdmR3ThreadWakeUp(pThread);
+ break;
+
+ case PDMTHREADSTATE_TERMINATING:
+ case PDMTHREADSTATE_TERMINATED:
+ break;
+
+ case PDMTHREADSTATE_INITIALIZING:
+ default:
+ AssertMsgFailed(("enmState=%d\n", enmState));
+ break;
+ }
+ break;
+ }
+}
+
+
+/**
+ * Suspends the thread.
+ *
+ * This can be called at the power off / suspend notifications to suspend the
+ * PDM thread a bit early. The thread will be automatically suspend upon
+ * completion of the device/driver notification cycle.
+ *
+ * The caller is responsible for serializing the control operations on the
+ * thread. That basically means, always do these calls from the EMT.
+ *
+ * @returns VBox status code.
+ * @param pThread The PDM thread.
+ */
+DECLHIDDEN(int) tstDevPdmR3ThreadSuspend(PPDMTHREAD pThread)
+{
+ /*
+ * Assert sanity.
+ */
+ AssertPtrReturn(pThread, VERR_INVALID_POINTER);
+ AssertReturn(pThread->u32Version == PDMTHREAD_VERSION, VERR_INVALID_MAGIC);
+ Assert(pThread->Thread != RTThreadSelf());
+
+ /*
+ * This is a noop if the thread is already suspended.
+ */
+ if (pThread->enmState == PDMTHREADSTATE_SUSPENDED)
+ return VINF_SUCCESS;
+
+ /*
+ * Change the state to resuming and kick the thread.
+ */
+ int rc = RTSemEventMultiReset(pThread->Internal.s.BlockEvent);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTThreadUserReset(pThread->Thread);
+ if (RT_SUCCESS(rc))
+ {
+ rc = VERR_WRONG_ORDER;
+ if (pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_SUSPENDING, PDMTHREADSTATE_RUNNING))
+ {
+ rc = pdmR3ThreadWakeUp(pThread);
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * Wait for the thread to reach the suspended state.
+ */
+ if (pThread->enmState != PDMTHREADSTATE_SUSPENDED)
+ rc = RTThreadUserWait(pThread->Thread, 60*1000);
+ if ( RT_SUCCESS(rc)
+ && pThread->enmState != PDMTHREADSTATE_SUSPENDED)
+ rc = VERR_PDM_THREAD_IPE_2;
+ if (RT_SUCCESS(rc))
+ return rc;
+ }
+ }
+ }
+ }
+
+ /*
+ * Something failed, initialize termination.
+ */
+ AssertMsgFailed(("PDMR3ThreadSuspend -> rc=%Rrc enmState=%d suspending '%s'\n",
+ rc, pThread->enmState, RTThreadGetName(pThread->Thread)));
+ pdmR3ThreadBailOut(pThread);
+ return rc;
+}
+
+
+/**
+ * Resumes the thread.
+ *
+ * This can be called the power on / resume notifications to resume the
+ * PDM thread a bit early. The thread will be automatically resumed upon
+ * return from these two notification callbacks (devices/drivers).
+ *
+ * The caller is responsible for serializing the control operations on the
+ * thread. That basically means, always do these calls from the EMT.
+ *
+ * @returns VBox status code.
+ * @param pThread The PDM thread.
+ */
+DECLHIDDEN(int) tstDevPdmR3ThreadResume(PPDMTHREAD pThread)
+{
+ /*
+ * Assert sanity.
+ */
+ AssertPtrReturn(pThread, VERR_INVALID_POINTER);
+ AssertReturn(pThread->u32Version == PDMTHREAD_VERSION, VERR_INVALID_MAGIC);
+ Assert(pThread->Thread != RTThreadSelf());
+
+ /*
+ * Change the state to resuming and kick the thread.
+ */
+ int rc = RTThreadUserReset(pThread->Thread);
+ if (RT_SUCCESS(rc))
+ {
+ rc = VERR_WRONG_ORDER;
+ if (pdmR3AtomicCmpXchgState(pThread, PDMTHREADSTATE_RESUMING, PDMTHREADSTATE_SUSPENDED))
+ {
+ rc = RTSemEventMultiSignal(pThread->Internal.s.BlockEvent);
+ if (RT_SUCCESS(rc))
+ {
+ /*
+ * Wait for the thread to reach the running state.
+ */
+ rc = RTThreadUserWait(pThread->Thread, 60*1000);
+ if ( RT_SUCCESS(rc)
+ && pThread->enmState != PDMTHREADSTATE_RUNNING)
+ rc = VERR_PDM_THREAD_IPE_2;
+ if (RT_SUCCESS(rc))
+ return rc;
+ }
+ }
+ }
+
+ /*
+ * Something failed, initialize termination.
+ */
+ AssertMsgFailed(("PDMR3ThreadResume -> rc=%Rrc enmState=%d\n", rc, pThread->enmState));
+ pdmR3ThreadBailOut(pThread);
+ return rc;
+}
+
diff --git a/src/VBox/Devices/testcase/tstDevicePlugin.h b/src/VBox/Devices/testcase/tstDevicePlugin.h
new file mode 100644
index 00000000..a125f1cd
--- /dev/null
+++ b/src/VBox/Devices/testcase/tstDevicePlugin.h
@@ -0,0 +1,100 @@
+/** @file
+ * tstDevice: Plugin API.
+ */
+
+/*
+ * Copyright (C) 2017-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+#ifndef VBOX_INCLUDED_SRC_testcase_tstDevicePlugin_h
+#define VBOX_INCLUDED_SRC_testcase_tstDevicePlugin_h
+#ifndef RT_WITHOUT_PRAGMA_ONCE
+# pragma once
+#endif
+
+#include <VBox/types.h>
+
+#include "tstDeviceCfg.h"
+
+
+/** Device under test handle. */
+typedef struct TSTDEVDUTINT *TSTDEVDUT;
+
+/**
+ * Testcase registration structure.
+ */
+typedef struct TSTDEVTESTCASEREG
+{
+ /** Testcase name. */
+ char szName[16];
+ /** Testcase description. */
+ const char *pszDesc;
+ /** Flags for this testcase. */
+ uint32_t fFlags;
+
+ /**
+ * Testcase entry point.
+ *
+ * @returns VBox status code.
+ * @param hDut Handle of the device under test.
+ * @param paCfg Pointer to the testcase config.
+ * @param cCfgItems Number of config items.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnTestEntry, (TSTDEVDUT hDut, PCTSTDEVCFGITEM paCfg, uint32_t cCfgItems));
+} TSTDEVTESTCASEREG;
+/** Pointer to a testcase registration structure. */
+typedef TSTDEVTESTCASEREG *PTSTDEVTESTCASEREG;
+/** Pointer to a constant testcase registration structure. */
+typedef const TSTDEVTESTCASEREG *PCTSTDEVTESTCASEREG;
+
+
+/**
+ * Testcase register callbacks structure.
+ */
+typedef struct TSTDEVPLUGINREGISTER
+{
+ /**
+ * Registers a new testcase.
+ *
+ * @returns VBox status code.
+ * @param pvUser Opaque user data given in the plugin load callback.
+ * @param pTestcaseReg The testcase descriptor to register.
+ */
+ DECLR3CALLBACKMEMBER(int, pfnRegisterTestcase, (void *pvUser, PCTSTDEVTESTCASEREG pTestcaseReg));
+
+} TSTDEVPLUGINREGISTER;
+/** Pointer to a backend register callbacks structure. */
+typedef TSTDEVPLUGINREGISTER *PTSTDEVPLUGINREGISTER;
+
+
+/**
+ * Initialization entry point called by the device test framework when
+ * a plugin is loaded.
+ *
+ * @returns VBox status code.
+ * @param pvUser Opaque user data passed in the register callbacks.
+ * @param pRegisterCallbacks Pointer to the register callbacks structure.
+ */
+typedef DECLCALLBACKTYPE(int, FNTSTDEVPLUGINLOAD,(void *pvUser, PTSTDEVPLUGINREGISTER pRegisterCallbacks));
+typedef FNTSTDEVPLUGINLOAD *PFNTSTDEVPLUGINLOAD;
+#define TSTDEV_PLUGIN_LOAD_NAME "TSTDevPluginLoad"
+
+#endif /* !VBOX_INCLUDED_SRC_testcase_tstDevicePlugin_h */
diff --git a/src/VBox/Devices/testcase/tstDeviceR0.cpp b/src/VBox/Devices/testcase/tstDeviceR0.cpp
new file mode 100644
index 00000000..4912c575
--- /dev/null
+++ b/src/VBox/Devices/testcase/tstDeviceR0.cpp
@@ -0,0 +1,163 @@
+/* $Id: tstDeviceR0.cpp $ */
+/** @file
+ * tstDevice - Test framework for PDM devices/drivers
+ */
+
+/*
+ * Copyright (C) 2017-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEFAULT /** @todo */
+#undef IN_RING3
+#undef IN_SUP_R3
+//#undef CTX_SUFF
+//#undef R0PTRTYPE
+//#undef R3PTRTYPE
+#define IN_RING0
+#define IN_SUP_R0
+#define LINUX_VERSION_CODE 0
+#define KERNEL_VERSION(a,b,c) 1
+//#define CTX_SUFF(a_Name) a_Name##R0
+//#define R3PTRTYPE(a_R3Type) RTHCUINTPTR
+//#define R0PTRTYPE(a_R0Type) a_R0Type
+#include <VBox/types.h>
+
+#include <VBox/sup.h>
+#include <VBox/version.h>
+#include <iprt/assert.h>
+#include <iprt/getopt.h>
+#include <iprt/log.h>
+#include <iprt/list.h>
+#include <iprt/mem.h>
+
+#include "tstDeviceInternal.h"
+#include "tstDeviceCfg.h"
+#include "tstDeviceBuiltin.h"
+
+
+
+/**
+ * Create a new PDM device with default config.
+ *
+ * @returns VBox status code.
+ * @param pszName Name of the device to create.
+ * @param fRCEnabled Flag whether RC support should be enabled for this device.
+ * @param pDut The device under test structure the created PDM device instance is exercised under.
+ */
+DECLHIDDEN(int) tstDevPdmDevR0R3Create(const char *pszName, bool fRCEnabled, PTSTDEVDUTINT pDut)
+{
+ int rc = VINF_SUCCESS;
+ PCPDMDEVREGR0 pPdmDevR0 = NULL;
+ PCTSTDEVPDMDEV pPdmDev = tstDevPdmDeviceFind(pszName, &pPdmDevR0);
+ if (RT_LIKELY(pPdmDev))
+ {
+ uint32_t const cbRing0 = RT_ALIGN_32(RT_UOFFSETOF(PDMDEVINSR0, achInstanceData) + pPdmDevR0->cbInstanceCC,
+ HOST_PAGE_SIZE);
+ uint32_t const cbRing3 = RT_ALIGN_32(RT_UOFFSETOF(PDMDEVINSR3, achInstanceData) + pPdmDev->pReg->cbInstanceCC,
+ fRCEnabled ? HOST_PAGE_SIZE : 64);
+ uint32_t const cbRC = fRCEnabled ? 0
+ : RT_ALIGN_32(RT_UOFFSETOF(PDMDEVINSRC, achInstanceData) + pPdmDevR0->cbInstanceRC, 64);
+ uint32_t const cbShared = RT_ALIGN_32(pPdmDev->pReg->cbInstanceShared, 64);
+ uint32_t const cbCritSect = RT_ALIGN_32(sizeof(PDMCRITSECT), 64);
+ uint32_t const cbMsixState = RT_ALIGN_32(pPdmDev->pReg->cMaxMsixVectors * 16 + (pPdmDev->pReg->cMaxMsixVectors + 7) / 8, _4K);
+ uint32_t const cbPciDev = RT_ALIGN_32(RT_UOFFSETOF_DYN(PDMPCIDEV, abMsixState[cbMsixState]), 64);
+ uint32_t const cPciDevs = RT_MIN(pPdmDev->pReg->cMaxPciDevices, 8);
+ uint32_t const cbPciDevs = cbPciDev * cPciDevs;
+ uint32_t const cbTotal = RT_ALIGN_32(cbRing0 + cbRing3 + cbRC + cbShared + cbCritSect + cbPciDevs, HOST_PAGE_SIZE);
+ AssertLogRelMsgReturn(cbTotal <= PDM_MAX_DEVICE_INSTANCE_SIZE,
+ ("Instance of '%s' is too big: cbTotal=%u, max %u\n",
+ pPdmDev->pReg->szName, cbTotal, PDM_MAX_DEVICE_INSTANCE_SIZE),
+ VERR_OUT_OF_RANGE);
+
+ PPDMDEVINSR0 pDevInsR0 = (PPDMDEVINSR0)RTMemAllocZ(cbTotal);
+ PDMDEVINSR3 *pDevInsR3 = (PDMDEVINSR3 *)(((uint8_t *)pDevInsR0 + cbRing0));
+
+ pDevInsR0->u32Version = PDM_DEVINSR0_VERSION;
+ pDevInsR0->iInstance = 0;
+ pDevInsR0->pHlpR0 = &g_tstDevPdmDevHlpR0;
+ pDevInsR0->Internal.s.pDut = pDut;
+ pDevInsR0->pvInstanceDataR0 = (uint8_t *)pDevInsR0 + cbRing0 + cbRing3 + cbRC;
+ pDevInsR0->pvInstanceDataForR0 = &pDevInsR0->achInstanceData[0];
+ pDevInsR0->pCritSectRoR0 = (PPDMCRITSECT)((uint8_t *)pDevInsR0->pvInstanceDataR0 + cbShared);
+ pDevInsR0->pReg = pPdmDevR0;
+ pDevInsR0->pDevInsForR3 = (RTHCUINTPTR)pDevInsR3;
+ pDevInsR0->pDevInsForR3R0 = pDevInsR3;
+ pDevInsR0->pvInstanceDataForR3R0 = &pDevInsR3->achInstanceData[0];
+ pDevInsR0->cbPciDev = cbPciDev;
+ pDevInsR0->cPciDevs = cPciDevs;
+ for (uint32_t iPciDev = 0; iPciDev < cPciDevs; iPciDev++)
+ {
+ /* Note! PDMDevice.cpp has a copy of this code. Keep in sync. */
+ PPDMPCIDEV pPciDev = (PPDMPCIDEV)((uint8_t *)pDevInsR0->pCritSectRoR0 + cbCritSect + cbPciDev * iPciDev);
+ if (iPciDev < RT_ELEMENTS(pDevInsR0->apPciDevs))
+ pDevInsR0->apPciDevs[iPciDev] = pPciDev;
+ pPciDev->cbConfig = _4K;
+ pPciDev->cbMsixState = cbMsixState;
+ pPciDev->idxSubDev = (uint16_t)iPciDev;
+ //pPciDev->Int.s.idxSubDev = (uint16_t)iPciDev;
+ pPciDev->u32Magic = PDMPCIDEV_MAGIC;
+ }
+
+ pDevInsR3->u32Version = PDM_DEVINSR3_VERSION;
+ pDevInsR3->iInstance = 0;
+ pDevInsR3->cbRing3 = cbRing3;
+ pDevInsR3->fR0Enabled = true;
+ pDevInsR3->fRCEnabled = fRCEnabled;
+ pDevInsR3->pvInstanceDataR3 = pDevInsR0->pDevInsForR3 + cbRing3 + cbRC;
+ pDevInsR3->pvInstanceDataForR3 = pDevInsR0->pDevInsForR3 + RT_UOFFSETOF(PDMDEVINSR3, achInstanceData);
+ pDevInsR3->pCritSectRoR3 = pDevInsR0->pDevInsForR3 + cbRing3 + cbRC + cbShared;
+ pDevInsR3->pDevInsR0RemoveMe = pDevInsR0;
+ pDevInsR3->pvInstanceDataR0 = pDevInsR0->pvInstanceDataR0;
+ pDevInsR3->pvInstanceDataRC = fRCEnabled ? NIL_RTRGPTR : pDevInsR0->pDevInsForRC + RT_UOFFSETOF(PDMDEVINSRC, achInstanceData);
+ pDevInsR3->pDevInsForRC = pDevInsR0->pDevInsForRC;
+ pDevInsR3->pDevInsForRCR3 = pDevInsR0->pDevInsForR3 + cbRing3;
+ pDevInsR3->pDevInsForRCR3 = pDevInsR3->pDevInsForRCR3 + RT_UOFFSETOF(PDMDEVINSRC, achInstanceData);
+ pDevInsR3->cbPciDev = cbPciDev;
+ pDevInsR3->cPciDevs = cPciDevs;
+ for (uint32_t i = 0; i < RT_MIN(cPciDevs, RT_ELEMENTS(pDevInsR3->apPciDevs)); i++)
+ pDevInsR3->apPciDevs[i] = pDevInsR3->pCritSectRoR3 + cbCritSect + cbPciDev * i;
+ RTCritSectInit(&pDevInsR0->pCritSectRoR0->s.CritSect);
+ pDut->pDevIns = pDevInsR3;
+ pDut->pDevInsR0 = pDevInsR0;
+
+ rc = tstDevPdmDeviceR3Construct(pDut);
+ if (RT_SUCCESS(rc))
+ {
+ rc = pPdmDevR0->pfnConstruct(pDevInsR0);
+ if (RT_SUCCESS(rc))
+ return VINF_SUCCESS;
+ }
+
+ if (RT_FAILURE(rc))
+ {
+ //rc = pPdmDev->pReg->pfnDestruct(pDevIns);
+ RTMemFree(pDevInsR0);
+ }
+ }
+ else
+ rc = VERR_NOT_FOUND;
+
+ return rc;
+}
diff --git a/src/VBox/Devices/testcase/tstDeviceSsmFuzz.cpp b/src/VBox/Devices/testcase/tstDeviceSsmFuzz.cpp
new file mode 100644
index 00000000..8bd2f46f
--- /dev/null
+++ b/src/VBox/Devices/testcase/tstDeviceSsmFuzz.cpp
@@ -0,0 +1,200 @@
+/* $Id: tstDeviceSsmFuzz.cpp $ */
+/** @file
+ * tstDeviceSsmFuzz - SSM fuzzing testcase.
+ */
+
+/*
+ * Copyright (C) 2020-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEFAULT /** @todo */
+#include <VBox/types.h>
+#include <iprt/errcore.h>
+#include <iprt/mem.h>
+#include <iprt/fuzz.h>
+#include <iprt/time.h>
+#include <iprt/string.h>
+
+#include "tstDeviceBuiltin.h"
+#include "tstDeviceCfg.h"
+#include "tstDeviceInternal.h"
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+
+
+static PCTSTDEVCFGITEM tstDevSsmFuzzGetCfgItem(PCTSTDEVCFGITEM paCfg, uint32_t cCfgItems, const char *pszName)
+{
+ for (uint32_t i = 0; i < cCfgItems; i++)
+ {
+ if (!RTStrCmp(paCfg[i].pszKey, pszName))
+ return &paCfg[i];
+ }
+
+ return NULL;
+}
+
+
+static const char *tstDevSsmFuzzGetCfgString(PCTSTDEVCFGITEM paCfg, uint32_t cCfgItems, const char *pszName)
+{
+ PCTSTDEVCFGITEM pCfgItem = tstDevSsmFuzzGetCfgItem(paCfg, cCfgItems, pszName);
+ if ( pCfgItem
+ && pCfgItem->enmType == TSTDEVCFGITEMTYPE_STRING)
+ return pCfgItem->u.psz;
+
+ return NULL;
+}
+
+
+static uint64_t tstDevSsmFuzzGetCfgU64(PCTSTDEVCFGITEM paCfg, uint32_t cCfgItems, const char *pszName)
+{
+ PCTSTDEVCFGITEM pCfgItem = tstDevSsmFuzzGetCfgItem(paCfg, cCfgItems, pszName);
+ if ( pCfgItem
+ && pCfgItem->enmType == TSTDEVCFGITEMTYPE_INTEGER)
+ return (uint64_t)pCfgItem->u.i64;
+
+ return 0;
+}
+
+
+static uint32_t tstDevSsmFuzzGetCfgU32(PCTSTDEVCFGITEM paCfg, uint32_t cCfgItems, const char *pszName)
+{
+ PCTSTDEVCFGITEM pCfgItem = tstDevSsmFuzzGetCfgItem(paCfg, cCfgItems, pszName);
+ if ( pCfgItem
+ && pCfgItem->enmType == TSTDEVCFGITEMTYPE_INTEGER)
+ return (uint32_t)pCfgItem->u.i64;
+
+ return 0;
+}
+
+
+/**
+ * Entry point for the SSM fuzzer.
+ *
+ * @returns VBox status code.
+ * @param hDut The device under test.
+ * @param paCfg The testcase config.
+ * @param cCfgItems Number of config items.
+ */
+static DECLCALLBACK(int) tstDevSsmFuzzEntry(TSTDEVDUT hDut, PCTSTDEVCFGITEM paCfg, uint32_t cCfgItems)
+{
+ RTFUZZCTX hFuzzCtx;
+ int rc = RTFuzzCtxCreate(&hFuzzCtx, RTFUZZCTXTYPE_BLOB);
+ if (RT_SUCCESS(rc))
+ {
+ RTFUZZCFG hFuzzCfg;
+ rc = RTFuzzCfgCreateFromFile(&hFuzzCfg, tstDevSsmFuzzGetCfgString(paCfg, cCfgItems, "CorpusPath"), NULL);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTFuzzCfgImport(hFuzzCfg, hFuzzCtx, RTFUZZCFG_IMPORT_F_DEFAULT);
+ RTFuzzCfgRelease(hFuzzCfg);
+ }
+
+ if (RT_SUCCESS(rc))
+ {
+ /* Create a new SSM handle to use. */
+ PSSMHANDLE pSsm = (PSSMHANDLE)RTMemAllocZ(sizeof(*pSsm));
+ if (RT_LIKELY(pSsm))
+ {
+ pSsm->pDut = hDut;
+ pSsm->pbSavedState = NULL;
+ pSsm->cbSavedState = 0;
+ pSsm->offDataBuffer = 0;
+ pSsm->uCurUnitVer = tstDevSsmFuzzGetCfgU32(paCfg, cCfgItems, "UnitVersion");
+ pSsm->rc = VINF_SUCCESS;
+
+ uint64_t cRuntimeMs = tstDevSsmFuzzGetCfgU64(paCfg, cCfgItems, "RuntimeSec") * RT_MS_1SEC_64;
+ uint64_t tsStart = RTTimeMilliTS();
+ uint64_t cFuzzedInputs = 0;
+ do
+ {
+ RTFUZZINPUT hFuzzInp;
+ rc = RTFuzzCtxInputGenerate(hFuzzCtx, &hFuzzInp);
+ if (RT_SUCCESS(rc))
+ {
+ void *pvBlob = NULL;
+ size_t cbBlob = 0;
+
+ rc = RTFuzzInputQueryBlobData(hFuzzInp, &pvBlob, &cbBlob);
+ if (RT_SUCCESS(rc))
+ {
+ pSsm->pbSavedState = (uint8_t *)pvBlob;
+ pSsm->cbSavedState = cbBlob;
+ pSsm->offDataBuffer = 0;
+ pSsm->rc = VINF_SUCCESS;
+
+ /* Get the SSM handler from the device. */
+ int rcDut = VINF_SUCCESS;
+ PTSTDEVDUTSSM pSsmClbks = RTListGetFirst(&hDut->LstSsmHandlers, TSTDEVDUTSSM, NdSsm);
+ if (pSsmClbks)
+ {
+ /* Load preparations. */
+ if (pSsmClbks->pfnLoadPrep)
+ rcDut = pSsmClbks->pfnLoadPrep(hDut->pDevIns, pSsm);
+ if (RT_SUCCESS(rcDut))
+ rcDut = pSsmClbks->pfnLoadExec(hDut->pDevIns, pSsm, pSsm->uCurUnitVer, SSM_PASS_FINAL);
+
+ cFuzzedInputs++;
+ }
+ if (RT_SUCCESS(rcDut))
+ RTFuzzInputAddToCtxCorpus(hFuzzInp);
+ }
+ RTFuzzInputRelease(hFuzzInp);
+ }
+ } while ( RT_SUCCESS(rc)
+ && RTTimeMilliTS() - tsStart < cRuntimeMs);
+
+ RTMemFree(pSsm);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+ }
+
+ RTFuzzCtxRelease(hFuzzCtx);
+ }
+
+ return rc;
+}
+
+
+const TSTDEVTESTCASEREG g_TestcaseSsmFuzz =
+{
+ /** szName */
+ "SsmFuzz",
+ /** pszDesc */
+ "Fuzzes devices SSM state loaders",
+ /** fFlags */
+ 0,
+ /** pfnTestEntry */
+ tstDevSsmFuzzEntry
+};
+
diff --git a/src/VBox/Devices/testcase/tstDeviceSsmLoadDbg.cpp b/src/VBox/Devices/testcase/tstDeviceSsmLoadDbg.cpp
new file mode 100644
index 00000000..860e1345
--- /dev/null
+++ b/src/VBox/Devices/testcase/tstDeviceSsmLoadDbg.cpp
@@ -0,0 +1,159 @@
+/* $Id: tstDeviceSsmLoadDbg.cpp $ */
+/** @file
+ * tstDeviceSsmFuzz - SSM fuzzing testcase.
+ */
+
+/*
+ * Copyright (C) 2020-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEFAULT /** @todo */
+#include <VBox/types.h>
+#include <iprt/errcore.h>
+#include <iprt/mem.h>
+#include <iprt/file.h>
+#include <iprt/fuzz.h>
+#include <iprt/time.h>
+#include <iprt/string.h>
+
+#include "tstDeviceBuiltin.h"
+#include "tstDeviceCfg.h"
+#include "tstDeviceInternal.h"
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+
+
+/*********************************************************************************************************************************
+* Structures and Typedefs *
+*********************************************************************************************************************************/
+
+
+static PCTSTDEVCFGITEM tstDevSsmFuzzGetCfgItem(PCTSTDEVCFGITEM paCfg, uint32_t cCfgItems, const char *pszName)
+{
+ for (uint32_t i = 0; i < cCfgItems; i++)
+ {
+ if (!RTStrCmp(paCfg[i].pszKey, pszName))
+ return &paCfg[i];
+ }
+
+ return NULL;
+}
+
+
+static const char *tstDevSsmFuzzGetCfgString(PCTSTDEVCFGITEM paCfg, uint32_t cCfgItems, const char *pszName)
+{
+ PCTSTDEVCFGITEM pCfgItem = tstDevSsmFuzzGetCfgItem(paCfg, cCfgItems, pszName);
+ if ( pCfgItem
+ && pCfgItem->enmType == TSTDEVCFGITEMTYPE_STRING)
+ return pCfgItem->u.psz;
+
+ return NULL;
+}
+
+
+static uint32_t tstDevSsmFuzzGetCfgU32(PCTSTDEVCFGITEM paCfg, uint32_t cCfgItems, const char *pszName)
+{
+ PCTSTDEVCFGITEM pCfgItem = tstDevSsmFuzzGetCfgItem(paCfg, cCfgItems, pszName);
+ if ( pCfgItem
+ && pCfgItem->enmType == TSTDEVCFGITEMTYPE_INTEGER)
+ return (uint32_t)pCfgItem->u.i64;
+
+ return 0;
+}
+
+
+/**
+ * Entry point for the SSM load debug.
+ *
+ * @returns VBox status code.
+ * @param hDut The device under test.
+ * @param paCfg The testcase config.
+ * @param cCfgItems Number of config items.
+ */
+static DECLCALLBACK(int) tstDevSsmLoadDbgEntry(TSTDEVDUT hDut, PCTSTDEVCFGITEM paCfg, uint32_t cCfgItems)
+{
+ int rc = VINF_SUCCESS;
+ const char *pszSsmUnit = tstDevSsmFuzzGetCfgString(paCfg, cCfgItems, "SsmUnit");
+ if (pszSsmUnit)
+ {
+ void *pvData = NULL;
+ size_t cbData = 0;
+
+ rc = RTFileReadAll(pszSsmUnit, &pvData, &cbData);
+ if (RT_SUCCESS(rc))
+ {
+ /* Create a new SSM handle to use. */
+ PSSMHANDLE pSsm = (PSSMHANDLE)RTMemAllocZ(sizeof(*pSsm));
+ if (RT_LIKELY(pSsm))
+ {
+ pSsm->pDut = hDut;
+ pSsm->pbSavedState = (uint8_t *)pvData;
+ pSsm->cbSavedState = cbData;
+ pSsm->offDataBuffer = 0;
+ pSsm->uCurUnitVer = tstDevSsmFuzzGetCfgU32(paCfg, cCfgItems, "UnitVersion");
+ pSsm->rc = VINF_SUCCESS;
+
+
+ /* Get the SSM handler from the device. */
+ int rcDut = VINF_SUCCESS;
+ PTSTDEVDUTSSM pSsmClbks = RTListGetFirst(&hDut->LstSsmHandlers, TSTDEVDUTSSM, NdSsm);
+ if (pSsmClbks)
+ {
+ /* Load preparations. */
+ if (pSsmClbks->pfnLoadPrep)
+ rcDut = pSsmClbks->pfnLoadPrep(hDut->pDevIns, pSsm);
+ if (RT_SUCCESS(rcDut))
+ rcDut = pSsmClbks->pfnLoadExec(hDut->pDevIns, pSsm, pSsm->uCurUnitVer, SSM_PASS_FINAL);
+ }
+ RTMemFree(pSsm);
+ }
+ else
+ rc = VERR_NO_MEMORY;
+
+ RTFileReadAllFree(pvData, cbData);
+ }
+ }
+ else
+ rc = VERR_NOT_FOUND;
+
+ return rc;
+}
+
+
+const TSTDEVTESTCASEREG g_TestcaseSsmLoadDbg =
+{
+ /** szName */
+ "SsmLoadDbg",
+ /** pszDesc */
+ "Load SSM states which fail to load in VBox for investigation",
+ /** fFlags */
+ 0,
+ /** pfnTestEntry */
+ tstDevSsmLoadDbgEntry
+};
+
diff --git a/src/VBox/Devices/testcase/tstDeviceStructSize.cpp b/src/VBox/Devices/testcase/tstDeviceStructSize.cpp
new file mode 100644
index 00000000..27b3790e
--- /dev/null
+++ b/src/VBox/Devices/testcase/tstDeviceStructSize.cpp
@@ -0,0 +1,454 @@
+/* $Id: tstDeviceStructSize.cpp $ */
+/** @file
+ * tstDeviceStructSize - testcase for check structure sizes/alignment
+ * and to verify that HC and RC uses the same
+ * representation of the structures.
+ */
+
+/*
+ * Copyright (C) 2006-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#include <VBox/types.h>
+#include <iprt/x86.h>
+
+#define VBOX_WITH_HGCM /* grumble */
+#define VBOX_DEVICE_STRUCT_TESTCASE
+
+/* Check that important preprocessor macros does not get redefined: */
+#include <VBox/cdefs.h>
+#include <VBox/log.h>
+#ifdef DEBUG
+# define VBOX_DEVICE_STRUCT_TESTCASE_CHECK_DEBUG
+#else
+# undef VBOX_DEVICE_STRUCT_TESTCASE_CHECK_DEBUG
+#endif
+#ifdef LOG_ENABLED
+# define VBOX_DEVICE_STRUCT_TESTCASE_CHECK_LOG_ENABLED
+#else
+# undef VBOX_DEVICE_STRUCT_TESTCASE_CHECK_LOG_ENABLED
+#endif
+#ifdef VBOX_STRICT
+# define VBOX_DEVICE_STRUCT_TESTCASE_CHECK_VBOX_STRICT
+#else
+# undef VBOX_DEVICE_STRUCT_TESTCASE_CHECK_VBOX_STRICT
+#endif
+#ifdef RT_STRICT
+# define VBOX_DEVICE_STRUCT_TESTCASE_CHECK_RT_STRICT
+#else
+# undef VBOX_DEVICE_STRUCT_TESTCASE_CHECK_RT_STRICT
+#endif
+
+/* The structures we're checking: */
+#undef LOG_GROUP
+#include "../Bus/DevPciInternal.h"
+#undef LOG_GROUP
+#include "../Graphics/DevVGA.cpp"
+#undef LOG_GROUP
+#include "../Input/DevPS2.h"
+#ifdef VBOX_WITH_E1000
+# undef LOG_GROUP
+# include "../Network/DevE1000.cpp"
+#endif
+#undef LOG_GROUP
+#include "../Network/DevPCNet.cpp"
+#undef LOG_GROUP
+#include "../PC/DevACPI.cpp"
+#undef LOG_GROUP
+#include "../PC/DevPIC.cpp"
+#undef LOG_GROUP
+#include "../PC/DevPit-i8254.cpp"
+#undef LOG_GROUP
+#include "../PC/DevRTC.cpp"
+# undef LOG_GROUP
+# include "../../VMM/VMMR3/APIC.cpp"
+#undef LOG_GROUP
+#include "../PC/DevIoApic.cpp"
+#undef LOG_GROUP
+#include "../PC/DevHPET.cpp"
+#undef LOG_GROUP
+#include "../PC/DevDMA.cpp"
+#undef LOG_GROUP
+#include "../EFI/DevSmc.cpp"
+#undef LOG_GROUP
+#include "../Storage/DevATA.cpp"
+#ifdef VBOX_WITH_USB
+# undef LOG_GROUP
+# include "../USB/DevOHCI.cpp"
+# ifdef VBOX_WITH_EHCI_IMPL
+# undef LOG_GROUP
+# include "../USB/DevEHCI.cpp"
+# endif
+# ifdef VBOX_WITH_XHCI_IMPL
+# undef LOG_GROUP
+# include "../USB/DevXHCI.cpp"
+# endif
+#endif
+#undef LOG_GROUP
+#include "../VMMDev/VMMDev.cpp"
+#undef LOG_GROUP
+#include "../Parallel/DevParallel.cpp"
+#undef LOG_GROUP
+#include "../Serial/DevSerial.cpp"
+#undef LOG_GROUP
+#include "../Serial/DevOxPcie958.cpp"
+#ifdef VBOX_WITH_AHCI
+# undef LOG_GROUP
+# include "../Storage/DevAHCI.cpp"
+#endif
+#ifdef VBOX_WITH_BUSLOGIC
+# undef LOG_GROUP
+# include "../Storage/DevBusLogic.cpp"
+#endif
+#ifdef VBOX_WITH_LSILOGIC
+# undef LOG_GROUP
+# include "../Storage/DevLsiLogicSCSI.cpp"
+#endif
+#ifdef VBOX_WITH_NVME_IMPL
+# undef LOG_GROUP
+# include "../Storage/DevNVMe.cpp"
+#endif
+
+#ifdef VBOX_WITH_PCI_PASSTHROUGH_IMPL
+# undef LOG_GROUP
+# include "../Bus/DevPciRaw.cpp"
+#endif
+
+#ifdef VBOX_WITH_IOMMU_AMD
+# undef LOG_GROUP
+# include "../Bus/DevIommuAmd.cpp"
+#endif
+#ifdef VBOX_WITH_IOMMU_INTEL
+# undef LOG_GROUP
+# include "../Bus/DevIommuIntel.cpp"
+#endif
+
+#include <VBox/vmm/pdmaudioifs.h>
+
+#undef LOG_GROUP
+#include "../Audio/DevIchAc97.cpp"
+#undef LOG_GROUP
+#include "../Audio/DevHda.h"
+
+
+/* Check that important preprocessor macros didn't get redefined: */
+#if defined(DEBUG) != defined(VBOX_DEVICE_STRUCT_TESTCASE_CHECK_DEBUG)
+# error "DEBUG was modified! This may throw off structure tests."
+#endif
+#if defined(LOG_ENABLED) != defined(VBOX_DEVICE_STRUCT_TESTCASE_CHECK_LOG_ENABLED)
+# error "LOG_ENABLED was modified! This may throw off structure tests."
+#endif
+#if defined(RT_STRICT) != defined(VBOX_DEVICE_STRUCT_TESTCASE_CHECK_RT_STRICT)
+# error "RT_STRICT was modified! This may throw off structure tests."
+#endif
+#if defined(VBOX_STRICT) != defined(VBOX_DEVICE_STRUCT_TESTCASE_CHECK_VBOX_STRICT)
+# error "VBOX_STRICT was modified! This may throw off structure tests."
+#endif
+
+
+#include <iprt/stream.h>
+
+
+/*********************************************************************************************************************************
+* Defined Constants And Macros *
+*********************************************************************************************************************************/
+/**
+ * Checks the offset of a data member.
+ * @param type Type.
+ * @param off Correct offset.
+ * @param m Member name.
+ */
+#define CHECK_OFF(type, off, m) \
+ do { \
+ if (off != RT_OFFSETOF(type, m)) \
+ { \
+ RTPrintf("tstDeviceStructSize: Error! %#010x %s Member offset wrong by %d (should be %d -- but is %d)\n", \
+ RT_OFFSETOF(type, m), #type "." #m, off - RT_OFFSETOF(type, m), off, RT_OFFSETOF(type, m)); \
+ rc++; \
+ } \
+ else \
+ RTPrintf("%#08x (%d) %s\n", RT_OFFSETOF(type, m), RT_OFFSETOF(type, m), #type "." #m); \
+ } while (0)
+
+/**
+ * Checks the size of type.
+ * @param type Type.
+ * @param size Correct size.
+ */
+#define CHECK_SIZE(type, size) \
+ do { \
+ if (size != sizeof(type)) \
+ { \
+ RTPrintf("tstDeviceStructSize: Error! sizeof(%s): %#x (%d) Size wrong by %d (should be %d -- but is %d)\n", \
+ #type, (int)sizeof(type), (int)sizeof(type), (int)sizeof(type) - (int)size, (int)size, (int)sizeof(type)); \
+ rc++; \
+ } \
+ else \
+ RTPrintf("tstDeviceStructSize: info: sizeof(%s): %#x (%d)\n", #type, (int)sizeof(type), (int)sizeof(type)); \
+ } while (0)
+
+/**
+ * Checks the alignment of a struct member.
+ */
+#define CHECK_MEMBER_ALIGNMENT(strct, member, align) \
+ do \
+ { \
+ if (RT_OFFSETOF(strct, member) & ((align) - 1) ) \
+ { \
+ RTPrintf("tstDeviceStructSize: error! %s::%s offset=%#x (%u) expected alignment %#x, meaning %#x (%u) off\n", \
+ #strct, #member, \
+ (unsigned)RT_OFFSETOF(strct, member), \
+ (unsigned)RT_OFFSETOF(strct, member), \
+ (unsigned)(align), \
+ (unsigned)(((align) - RT_OFFSETOF(strct, member)) & ((align) - 1)), \
+ (unsigned)(((align) - RT_OFFSETOF(strct, member)) & ((align) - 1)) ); \
+ rc++; \
+ } \
+ } while (0)
+
+/**
+ * Checks that the size of a type is aligned correctly.
+ */
+#define CHECK_SIZE_ALIGNMENT(type, align) \
+ do { \
+ if (RT_ALIGN_Z(sizeof(type), (align)) != sizeof(type)) \
+ { \
+ RTPrintf("tstDeviceStructSize: error! %s size=%#x (%u), align=%#x %#x (%u) bytes off\n", \
+ #type, \
+ (unsigned)sizeof(type), \
+ (unsigned)sizeof(type), \
+ (align), \
+ (unsigned)RT_ALIGN_Z(sizeof(type), align) - (unsigned)sizeof(type), \
+ (unsigned)RT_ALIGN_Z(sizeof(type), align) - (unsigned)sizeof(type)); \
+ rc++; \
+ } \
+ } while (0)
+
+/**
+ * Checks that a internal struct padding is big enough.
+ */
+#define CHECK_PADDING(strct, member, align) \
+ do \
+ { \
+ strct *p = NULL; NOREF(p); \
+ if (sizeof(p->member.s) > sizeof(p->member.padding)) \
+ { \
+ RTPrintf("tstDeviceStructSize: error! padding of %s::%s is too small, padding=%d struct=%d correct=%d\n", #strct, #member, \
+ (int)sizeof(p->member.padding), (int)sizeof(p->member.s), (int)RT_ALIGN_Z(sizeof(p->member.s), (align))); \
+ rc++; \
+ } \
+ else if (RT_ALIGN_Z(sizeof(p->member.padding), (align)) != sizeof(p->member.padding)) \
+ { \
+ RTPrintf("tstDeviceStructSize: error! padding of %s::%s is misaligned, padding=%d correct=%d\n", #strct, #member, \
+ (int)sizeof(p->member.padding), (int)RT_ALIGN_Z(sizeof(p->member.s), (align))); \
+ rc++; \
+ } \
+ } while (0)
+
+/**
+ * Checks that a internal struct padding is big enough.
+ */
+#define CHECK_PADDING2(strct) \
+ do \
+ { \
+ strct *p = NULL; NOREF(p); \
+ if (sizeof(p->s) > sizeof(p->padding)) \
+ { \
+ RTPrintf("tstDeviceStructSize: error! padding of %s is too small, padding=%d struct=%d correct=%d\n", #strct, \
+ (int)sizeof(p->padding), (int)sizeof(p->s), (int)RT_ALIGN_Z(sizeof(p->s), 32)); \
+ rc++; \
+ } \
+ } while (0)
+
+/**
+ * Checks that a internal struct padding is big enough.
+ */
+#define CHECK_PADDING3(strct, member, pad_member) \
+ do \
+ { \
+ strct *p = NULL; NOREF(p); \
+ if (sizeof(p->member) > sizeof(p->pad_member)) \
+ { \
+ RTPrintf("tstDeviceStructSize: error! padding of %s::%s is too small, padding=%d struct=%d\n", #strct, #member, \
+ (int)sizeof(p->pad_member), (int)sizeof(p->member)); \
+ rc++; \
+ } \
+ } while (0)
+
+/**
+ * Prints the offset of a struct member.
+ */
+#define PRINT_OFFSET(strct, member) \
+ do \
+ { \
+ RTPrintf("tstDeviceStructSize: info: %s::%s offset %d sizeof %d\n", #strct, #member, (int)RT_OFFSETOF(strct, member), (int)RT_SIZEOFMEMB(strct, member)); \
+ } while (0)
+
+
+int main()
+{
+ int rc = 0;
+ RTPrintf("tstDeviceStructSize: TESTING\n");
+
+ /* Assert sanity */
+ CHECK_SIZE(uint128_t, 128/8);
+ CHECK_SIZE(int128_t, 128/8);
+ CHECK_SIZE(uint64_t, 64/8);
+ CHECK_SIZE(int64_t, 64/8);
+ CHECK_SIZE(uint32_t, 32/8);
+ CHECK_SIZE(int32_t, 32/8);
+ CHECK_SIZE(uint16_t, 16/8);
+ CHECK_SIZE(int16_t, 16/8);
+ CHECK_SIZE(uint8_t, 8/8);
+ CHECK_SIZE(int8_t, 8/8);
+
+ /* Basic alignment checks. */
+ CHECK_MEMBER_ALIGNMENT(PDMDEVINS, achInstanceData, 64);
+ CHECK_MEMBER_ALIGNMENT(PDMPCIDEV, Int.s, 16);
+ CHECK_MEMBER_ALIGNMENT(PDMPCIDEV, Int.s.aIORegions, 16);
+
+ /*
+ * Misc alignment checks (keep this somewhat alphabetical).
+ */
+ CHECK_MEMBER_ALIGNMENT(AC97STATE, CritSect, 8);
+
+ CHECK_MEMBER_ALIGNMENT(AHCI, lock, 8);
+ CHECK_MEMBER_ALIGNMENT(AHCI, aPorts[0], 8);
+ CHECK_MEMBER_ALIGNMENT(AHCIR3, aPorts[0], 8);
+
+ CHECK_MEMBER_ALIGNMENT(ATADEVSTATE, cTotalSectors, 8);
+ CHECK_MEMBER_ALIGNMENT(ATADEVSTATE, StatATADMA, 8);
+ CHECK_MEMBER_ALIGNMENT(ATADEVSTATE, StatReads, 8);
+ CHECK_MEMBER_ALIGNMENT(ATACONTROLLER, lock, 8);
+ CHECK_MEMBER_ALIGNMENT(ATACONTROLLER, StatAsyncOps, 8);
+ CHECK_MEMBER_ALIGNMENT(BUSLOGIC, CritSectIntr, 8);
+#ifdef VBOX_WITH_STATISTICS
+ CHECK_MEMBER_ALIGNMENT(DEVPIC, StatSetIrqRZ, 8);
+#endif
+#ifdef VBOX_WITH_E1000
+ CHECK_MEMBER_ALIGNMENT(E1KSTATE, cs, 8);
+ CHECK_MEMBER_ALIGNMENT(E1KSTATE, csRx, 8);
+ CHECK_MEMBER_ALIGNMENT(E1KSTATE, StatReceiveBytes, 8);
+#endif
+ //CHECK_MEMBER_ALIGNMENT(E1KSTATE, csTx, 8);
+#ifdef VBOX_WITH_USB
+# ifdef VBOX_WITH_EHCI_IMPL
+ CHECK_MEMBER_ALIGNMENT(EHCI, RootHub, 8);
+# endif
+# ifdef VBOX_WITH_XHCI_IMPL
+ CHECK_MEMBER_ALIGNMENT(XHCI, aPorts, 8);
+ CHECK_MEMBER_ALIGNMENT(XHCI, aInterrupters, 8);
+ CHECK_MEMBER_ALIGNMENT(XHCI, aInterrupters[0].lock, 8);
+ CHECK_MEMBER_ALIGNMENT(XHCI, aInterrupters[1].lock, 8);
+ CHECK_MEMBER_ALIGNMENT(XHCI, cmdr_dqp, 8);
+ CHECK_MEMBER_ALIGNMENT(XHCI, hMmio, 8);
+# ifdef VBOX_WITH_STATISTICS
+ CHECK_MEMBER_ALIGNMENT(XHCI, StatErrorIsocUrbs, 8);
+ CHECK_MEMBER_ALIGNMENT(XHCI, StatIntrsCleared, 8);
+# endif
+# endif
+#endif
+ CHECK_MEMBER_ALIGNMENT(E1KSTATE, StatReceiveBytes, 8);
+ CHECK_MEMBER_ALIGNMENT(IOAPIC, au64RedirTable, 8);
+# ifdef VBOX_WITH_STATISTICS
+ CHECK_MEMBER_ALIGNMENT(IOAPIC, StatMmioReadRZ, 8);
+# endif
+ CHECK_MEMBER_ALIGNMENT(LSILOGICSCSI, aMessage, 8);
+ CHECK_MEMBER_ALIGNMENT(LSILOGICSCSI, ReplyPostQueueCritSect, 8);
+ CHECK_MEMBER_ALIGNMENT(LSILOGICSCSI, ReplyFreeQueueCritSect, 8);
+ CHECK_MEMBER_ALIGNMENT(LSILOGICSCSI, uReplyFreeQueueNextEntryFreeWrite, 8);
+#ifdef VBOX_WITH_USB
+ CHECK_MEMBER_ALIGNMENT(OHCI, RootHub, 8);
+# ifdef VBOX_WITH_STATISTICS
+ CHECK_MEMBER_ALIGNMENT(OHCI, StatCanceledIsocUrbs, 8);
+# endif
+#endif
+ CHECK_MEMBER_ALIGNMENT(DEVPCIBUS, apDevices, 64);
+ CHECK_MEMBER_ALIGNMENT(DEVPCIROOT, auPciApicIrqLevels, 16);
+ CHECK_MEMBER_ALIGNMENT(DEVPCIROOT, Piix3.auPciLegacyIrqLevels, 16);
+ CHECK_MEMBER_ALIGNMENT(PCNETSTATE, u64LastPoll, 8);
+ CHECK_MEMBER_ALIGNMENT(PCNETSTATE, CritSect, 8);
+ CHECK_MEMBER_ALIGNMENT(PCNETSTATE, StatReceiveBytes, 8);
+#ifdef VBOX_WITH_STATISTICS
+ CHECK_MEMBER_ALIGNMENT(PCNETSTATE, StatMMIOReadRZ, 8);
+#endif
+ CHECK_MEMBER_ALIGNMENT(PITSTATE, StatPITIrq, 8);
+ CHECK_MEMBER_ALIGNMENT(DEVSERIAL, UartCore, 8);
+ CHECK_MEMBER_ALIGNMENT(UARTCORE, CritSect, 8);
+#ifdef VBOX_WITH_VMSVGA
+ CHECK_SIZE(VMSVGAState, RT_ALIGN_Z(sizeof(VMSVGAState), 8));
+ CHECK_MEMBER_ALIGNMENT(VGASTATE, svga, 8);
+ CHECK_MEMBER_ALIGNMENT(VGASTATE, svga.au32ScratchRegion, 8);
+ CHECK_MEMBER_ALIGNMENT(VGASTATE, svga.StatRegBitsPerPixelWr, 8);
+#endif
+ CHECK_MEMBER_ALIGNMENT(VGASTATE, cMonitors, 8);
+ CHECK_MEMBER_ALIGNMENT(VGASTATE, GCPhysVRAM, 8);
+ CHECK_MEMBER_ALIGNMENT(VGASTATE, CritSect, 8);
+ CHECK_MEMBER_ALIGNMENT(VGASTATE, StatRZMemoryRead, 8);
+ CHECK_MEMBER_ALIGNMENT(VGASTATE, CritSectIRQ, 8);
+ CHECK_MEMBER_ALIGNMENT(VGASTATE, bmDirtyBitmap, 8);
+ CHECK_MEMBER_ALIGNMENT(VGASTATE, pciRegions, 8);
+ CHECK_MEMBER_ALIGNMENT(VMMDEV, CritSect, 8);
+#ifdef VBOX_WITH_PCI_PASSTHROUGH_IMPL
+ CHECK_MEMBER_ALIGNMENT(PCIRAWSENDREQ, u.aGetRegionInfo.u64RegionSize, 8);
+#endif
+#ifdef VBOX_WITH_IOMMU_AMD
+ CHECK_MEMBER_ALIGNMENT(IOMMU, IommuBar, 8);
+ CHECK_MEMBER_ALIGNMENT(IOMMU, aDevTabBaseAddrs, 8);
+ CHECK_MEMBER_ALIGNMENT(IOMMU, CmdBufHeadPtr, 8);
+ CHECK_MEMBER_ALIGNMENT(IOMMU, Status, 8);
+# ifdef VBOX_WITH_STATISTICS
+ CHECK_MEMBER_ALIGNMENT(IOMMU, StatMmioReadR3, 8);
+# endif
+#endif
+#ifdef VBOX_WITH_IOMMU_INTEL
+ CHECK_MEMBER_ALIGNMENT(DMAR, abRegs0, 8);
+ CHECK_MEMBER_ALIGNMENT(DMAR, abRegs1, 8);
+ CHECK_MEMBER_ALIGNMENT(DMAR, uIrtaReg, 8);
+ CHECK_MEMBER_ALIGNMENT(DMAR, uRtaddrReg, 8);
+ CHECK_MEMBER_ALIGNMENT(DMAR, hEvtInvQueue, 8);
+# ifdef VBOX_WITH_STATISTICS
+ CHECK_MEMBER_ALIGNMENT(DMAR, StatMmioReadR3, 8);
+ CHECK_MEMBER_ALIGNMENT(DMAR, StatPasidDevtlbInvDsc, 8);
+# endif
+#endif
+
+#ifdef VBOX_WITH_RAW_MODE
+ /*
+ * Compare HC and RC.
+ */
+ RTPrintf("tstDeviceStructSize: Comparing HC and RC...\n");
+# include "tstDeviceStructSizeRC.h"
+#endif
+
+ /*
+ * Report result.
+ */
+ if (rc)
+ RTPrintf("tstDeviceStructSize: FAILURE - %d errors\n", rc);
+ else
+ RTPrintf("tstDeviceStructSize: SUCCESS\n");
+ return rc;
+}
diff --git a/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp b/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
new file mode 100644
index 00000000..70e3d588
--- /dev/null
+++ b/src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp
@@ -0,0 +1,2264 @@
+/* $Id: tstDeviceStructSizeRC.cpp $ */
+/** @file
+ * tstDeviceStructSizeGC - Generate structure member and size checks from the RC perspective.
+ *
+ * This is built using the VBoxRc template but linked into a host
+ * ring-3 executable, rather hacky.
+ */
+
+/*
+ * Copyright (C) 2006-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+
+/*
+ * Sanity checks.
+ */
+#ifndef IN_RC
+# error Incorrect template!
+#endif
+#if defined(IN_RING3) || defined(IN_RING0)
+# error Incorrect template!
+#endif
+
+
+/*********************************************************************************************************************************
+* Header Files *
+*********************************************************************************************************************************/
+#define VBOX_DEVICE_STRUCT_TESTCASE
+#define VBOX_WITH_HGCM /* grumble */
+
+/* Check that important preprocessor macros does not get redefined: */
+#include <VBox/cdefs.h>
+#include <VBox/log.h>
+#ifdef DEBUG
+# define VBOX_DEVICE_STRUCT_TESTCASE_CHECK_DEBUG
+#else
+# undef VBOX_DEVICE_STRUCT_TESTCASE_CHECK_DEBUG
+#endif
+#ifdef LOG_ENABLED
+# define VBOX_DEVICE_STRUCT_TESTCASE_CHECK_LOG_ENABLED
+#else
+# undef VBOX_DEVICE_STRUCT_TESTCASE_CHECK_LOG_ENABLED
+#endif
+#ifdef VBOX_STRICT
+# define VBOX_DEVICE_STRUCT_TESTCASE_CHECK_VBOX_STRICT
+#else
+# undef VBOX_DEVICE_STRUCT_TESTCASE_CHECK_VBOX_STRICT
+#endif
+#ifdef RT_STRICT
+# define VBOX_DEVICE_STRUCT_TESTCASE_CHECK_RT_STRICT
+#else
+# undef VBOX_DEVICE_STRUCT_TESTCASE_CHECK_RT_STRICT
+#endif
+
+/* The structures we're checking: */
+#undef LOG_GROUP
+#include "../Bus/DevPciInternal.h"
+#undef LOG_GROUP
+#include "../EFI/DevSmc.cpp"
+#undef LOG_GROUP
+#include "../Graphics/DevVGA.cpp"
+#undef LOG_GROUP
+#include "../Input/DevPS2.cpp"
+#undef LOG_GROUP
+#include "../Input/PS2K.cpp"
+#undef LOG_GROUP
+#include "../Input/PS2M.cpp"
+#undef LOG_GROUP
+#include "../Network/DevPCNet.cpp"
+#undef LOG_GROUP
+#include "../PC/DevACPI.cpp"
+#undef LOG_GROUP
+#include "../PC/DevPIC.cpp"
+#undef LOG_GROUP
+#include "../PC/DevPit-i8254.cpp"
+#undef LOG_GROUP
+#include "../PC/DevRTC.cpp"
+# undef LOG_GROUP
+# include "../../VMM/VMMR3/APIC.cpp"
+#undef LOG_GROUP
+#include "../PC/DevIoApic.cpp"
+#undef LOG_GROUP
+#include "../PC/DevDMA.cpp"
+#undef LOG_GROUP
+#include "../Storage/DevATA.cpp"
+#ifdef VBOX_WITH_USB
+# undef LOG_GROUP
+# include "../USB/DevOHCI.cpp"
+# ifdef VBOX_WITH_EHCI_IMPL
+# undef LOG_GROUP
+# include "../USB/DevEHCI.cpp"
+# endif
+# ifdef VBOX_WITH_XHCI_IMPL
+# undef LOG_GROUP
+# include "../USB/DevXHCI.cpp"
+# endif
+#endif
+#undef LOG_GROUP
+#include "../VMMDev/VMMDev.cpp"
+#undef LOG_GROUP
+#include "../Parallel/DevParallel.cpp"
+#undef LOG_GROUP
+#include "../Serial/DevSerial.cpp"
+#undef LOG_GROUP
+#include "../Serial/DevOxPcie958.cpp"
+#undef LOG_GROUP
+#include "../Serial/UartCore.h"
+#ifdef VBOX_WITH_AHCI
+# undef LOG_GROUP
+# include "../Storage/DevAHCI.cpp"
+#endif
+#ifdef VBOX_WITH_E1000
+# undef LOG_GROUP
+# include "../Network/DevE1000.cpp"
+#endif
+#ifdef VBOX_WITH_BUSLOGIC
+# undef LOG_GROUP
+# include "../Storage/DevBusLogic.cpp"
+#endif
+#ifdef VBOX_WITH_LSILOGIC
+# undef LOG_GROUP
+# include "../Storage/DevLsiLogicSCSI.cpp"
+#endif
+#undef LOG_GROUP
+#include "../PC/DevHPET.cpp"
+#undef LOG_GROUP
+#include "../Audio/DevIchAc97.cpp"
+#undef LOG_GROUP
+#include "../Audio/DevHDA.cpp"
+#ifdef VBOX_WITH_NVME_IMPL
+# undef LOG_GROUP
+# include "../Storage/DevNVMe.cpp"
+#endif
+#ifdef VBOX_WITH_IOMMU_AMD
+# undef LOG_GROUP
+# include "../Bus/DevIommuAmd.cpp"
+#endif
+#ifdef VBOX_WITH_IOMMU_INTEL
+# undef LOG_GROUP
+# include "../Bus/DevIommuIntel.cpp"
+#endif
+
+/* Check that important preprocessor macros didn't get redefined: */
+#if defined(DEBUG) != defined(VBOX_DEVICE_STRUCT_TESTCASE_CHECK_DEBUG)
+# error "DEBUG was modified! This may throw off structure tests."
+#endif
+#if defined(LOG_ENABLED) != defined(VBOX_DEVICE_STRUCT_TESTCASE_CHECK_LOG_ENABLED)
+# error "LOG_ENABLED was modified! This may throw off structure tests."
+#endif
+#if defined(RT_STRICT) != defined(VBOX_DEVICE_STRUCT_TESTCASE_CHECK_RT_STRICT)
+# error "RT_STRICT was modified! This may throw off structure tests."
+#endif
+#if defined(VBOX_STRICT) != defined(VBOX_DEVICE_STRUCT_TESTCASE_CHECK_VBOX_STRICT)
+# error "VBOX_STRICT was modified! This may throw off structure tests."
+#endif
+
+
+/* we don't use iprt here because we're pretending to be in GC! */
+#include <stdio.h>
+
+#define GEN_CHECK_SIZE(s) printf(" CHECK_SIZE(%s, %d);\n", #s, (int)sizeof(s))
+#define GEN_CHECK_OFF(s, m) printf(" CHECK_OFF(%s, %d, %s);\n", #s, (int)RT_OFFSETOF(s, m), #m)
+#define GEN_CHECK_PADDING(s, m, a) printf(" CHECK_PADDING(%s, %s, %u);\n", #s, #m, (a))
+
+int main()
+{
+ /* misc */
+ GEN_CHECK_SIZE(PDMDEVINS);
+ GEN_CHECK_OFF(PDMDEVINS, Internal);
+ GEN_CHECK_OFF(PDMDEVINS, pReg);
+ GEN_CHECK_OFF(PDMDEVINS, pCfg);
+ GEN_CHECK_OFF(PDMDEVINS, iInstance);
+ GEN_CHECK_OFF(PDMDEVINS, IBase);
+ GEN_CHECK_OFF(PDMDEVINS, pHlpR3);
+ GEN_CHECK_OFF(PDMDEVINS, pHlpR0);
+ GEN_CHECK_OFF(PDMDEVINS, pHlpRC);
+ GEN_CHECK_OFF(PDMDEVINS, pvInstanceDataR3);
+ GEN_CHECK_OFF(PDMDEVINS, pvInstanceDataR0);
+ GEN_CHECK_OFF(PDMDEVINS, pvInstanceDataRC);
+ GEN_CHECK_OFF(PDMDEVINS, achInstanceData);
+
+ /* PDMPCIDEV */
+ GEN_CHECK_SIZE(PDMPCIDEV);
+ GEN_CHECK_SIZE(PDMPCIDEVINT);
+ GEN_CHECK_SIZE(PCIIOREGION); /** @todo fix name of PCIIOREGION */
+ GEN_CHECK_OFF(PDMPCIDEV, abConfig);
+ GEN_CHECK_OFF(PDMPCIDEV, uDevFn);
+ GEN_CHECK_OFF(PDMPCIDEV, pszNameR3);
+ GEN_CHECK_OFF(PDMPCIDEV, pfnRegionLoadChangeHookR3);
+ GEN_CHECK_OFF(PDMPCIDEV, Int);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.aIORegions);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.aIORegions[1]);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.aIORegions[VBOX_PCI_NUM_REGIONS - 1]);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.aIORegions[0].addr);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.aIORegions[0].size);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.aIORegions[0].type);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.aIORegions[0].padding);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.pBusR3);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.pBusR0);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.pBusRC);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.pfnConfigRead);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.pfnConfigWrite);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.fFlags);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.uIrqPinState);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.pfnBridgeConfigRead);
+ GEN_CHECK_OFF(PDMPCIDEV, Int.s.pfnBridgeConfigWrite);
+ GEN_CHECK_PADDING(PDMPCIDEV, Int, 8);
+
+ /* DevPciInternal.h */
+ GEN_CHECK_SIZE(DEVPCIBUS);
+ GEN_CHECK_OFF(DEVPCIBUS, iBus);
+ GEN_CHECK_OFF(DEVPCIBUS, iDevSearch);
+ GEN_CHECK_OFF(DEVPCIBUS, cBridges);
+ GEN_CHECK_OFF(DEVPCIBUS, apDevices);
+ GEN_CHECK_OFF(DEVPCIBUS, apDevices[1]);
+ GEN_CHECK_OFF(DEVPCIBUS, papBridgesR3);
+ GEN_CHECK_OFF(DEVPCIBUS, PciDev);
+ GEN_CHECK_SIZE(PIIX3ISABRIDGE);
+ GEN_CHECK_SIZE(DEVPCIROOT);
+ GEN_CHECK_OFF(DEVPCIROOT, PciBus);
+ GEN_CHECK_OFF(DEVPCIROOT, fUseIoApic);
+ GEN_CHECK_OFF(DEVPCIROOT, u64PciConfigMMioAddress);
+ GEN_CHECK_OFF(DEVPCIROOT, u64PciConfigMMioLength);
+ GEN_CHECK_OFF(DEVPCIROOT, auPciApicIrqLevels);
+ GEN_CHECK_OFF(DEVPCIROOT, auPciApicIrqLevels[1]);
+ GEN_CHECK_OFF(DEVPCIROOT, uConfigReg);
+ GEN_CHECK_OFF(DEVPCIROOT, Piix3.iAcpiIrqLevel);
+ GEN_CHECK_OFF(DEVPCIROOT, Piix3.iAcpiIrq);
+ GEN_CHECK_OFF(DEVPCIROOT, Piix3.auPciLegacyIrqLevels);
+ GEN_CHECK_OFF(DEVPCIROOT, Piix3.auPciLegacyIrqLevels[1]);
+ GEN_CHECK_OFF(DEVPCIROOT, Piix3.PIIX3State);
+ GEN_CHECK_OFF(DEVPCIROOT, uPciBiosBus);
+ GEN_CHECK_OFF(DEVPCIROOT, uPciBiosIo);
+ GEN_CHECK_OFF(DEVPCIROOT, uPciBiosMmio);
+ GEN_CHECK_OFF(DEVPCIROOT, uPciBiosMmio64);
+
+ /* EFI/DevSMC.cpp */
+ GEN_CHECK_SIZE(DEVSMC);
+ GEN_CHECK_OFF(DEVSMC, bCmd);
+ GEN_CHECK_OFF(DEVSMC, offKey);
+ GEN_CHECK_OFF(DEVSMC, offValue);
+ GEN_CHECK_OFF(DEVSMC, cKeys);
+ GEN_CHECK_OFF(DEVSMC, CurKey);
+ GEN_CHECK_OFF(DEVSMC, u);
+ GEN_CHECK_OFF(DEVSMC, u.s);
+ GEN_CHECK_OFF(DEVSMC, u.s.bState);
+ GEN_CHECK_OFF(DEVSMC, u.s.bStatusCode);
+ GEN_CHECK_OFF(DEVSMC, u.s.bStatusCode);
+ GEN_CHECK_OFF(DEVSMC, szOsk0And1);
+ GEN_CHECK_OFF(DEVSMC, bDollaryNumber);
+ GEN_CHECK_OFF(DEVSMC, bShutdownReason);
+ GEN_CHECK_OFF(DEVSMC, bNinjaActionTimerJob);
+
+ /* DevVGA.cpp */
+ GEN_CHECK_SIZE(VGASTATE);
+ GEN_CHECK_OFF(VGASTATE, vram_ptrR3);
+ GEN_CHECK_OFF(VGASTATE, get_bpp);
+ GEN_CHECK_OFF(VGASTATE, get_offsets);
+ GEN_CHECK_OFF(VGASTATE, get_resolution);
+ GEN_CHECK_OFF(VGASTATE, rgb_to_pixel);
+ GEN_CHECK_OFF(VGASTATE, cursor_invalidate);
+ GEN_CHECK_OFF(VGASTATE, cursor_draw_line);
+ GEN_CHECK_OFF(VGASTATE, vram_size);
+ GEN_CHECK_OFF(VGASTATE, latch);
+ GEN_CHECK_OFF(VGASTATE, sr_index);
+ GEN_CHECK_OFF(VGASTATE, sr);
+ GEN_CHECK_OFF(VGASTATE, sr[1]);
+ GEN_CHECK_OFF(VGASTATE, gr_index);
+ GEN_CHECK_OFF(VGASTATE, gr);
+ GEN_CHECK_OFF(VGASTATE, gr[1]);
+ GEN_CHECK_OFF(VGASTATE, ar_index);
+ GEN_CHECK_OFF(VGASTATE, ar);
+ GEN_CHECK_OFF(VGASTATE, ar[1]);
+ GEN_CHECK_OFF(VGASTATE, ar_flip_flop);
+ GEN_CHECK_OFF(VGASTATE, cr_index);
+ GEN_CHECK_OFF(VGASTATE, cr);
+ GEN_CHECK_OFF(VGASTATE, cr[1]);
+ GEN_CHECK_OFF(VGASTATE, msr);
+ GEN_CHECK_OFF(VGASTATE, msr);
+ GEN_CHECK_OFF(VGASTATE, fcr);
+ GEN_CHECK_OFF(VGASTATE, st00);
+ GEN_CHECK_OFF(VGASTATE, st01);
+ GEN_CHECK_OFF(VGASTATE, dac_state);
+ GEN_CHECK_OFF(VGASTATE, dac_sub_index);
+ GEN_CHECK_OFF(VGASTATE, dac_read_index);
+ GEN_CHECK_OFF(VGASTATE, dac_write_index);
+ GEN_CHECK_OFF(VGASTATE, dac_cache);
+ GEN_CHECK_OFF(VGASTATE, dac_cache[1]);
+ GEN_CHECK_OFF(VGASTATE, palette);
+ GEN_CHECK_OFF(VGASTATE, palette[1]);
+ GEN_CHECK_OFF(VGASTATE, bank_offset);
+#ifdef CONFIG_BOCHS_VBE
+ GEN_CHECK_OFF(VGASTATE, vbe_index);
+ GEN_CHECK_OFF(VGASTATE, vbe_regs);
+ GEN_CHECK_OFF(VGASTATE, vbe_regs[1]);
+ GEN_CHECK_OFF(VGASTATE, vbe_regs[VBE_DISPI_INDEX_NB - 1]);
+ GEN_CHECK_OFF(VGASTATE, vbe_start_addr);
+ GEN_CHECK_OFF(VGASTATE, vbe_line_offset);
+ GEN_CHECK_OFF(VGASTATE, vbe_bank_max);
+#endif
+ GEN_CHECK_OFF(VGASTATE, font_offsets);
+ GEN_CHECK_OFF(VGASTATE, font_offsets[1]);
+ GEN_CHECK_OFF(VGASTATE, graphic_mode);
+ GEN_CHECK_OFF(VGASTATE, shift_control);
+ GEN_CHECK_OFF(VGASTATE, double_scan);
+ GEN_CHECK_OFF(VGASTATE, line_offset);
+ GEN_CHECK_OFF(VGASTATE, line_compare);
+ GEN_CHECK_OFF(VGASTATE, start_addr);
+ GEN_CHECK_OFF(VGASTATE, plane_updated);
+ GEN_CHECK_OFF(VGASTATE, last_cw);
+ GEN_CHECK_OFF(VGASTATE, last_ch);
+ GEN_CHECK_OFF(VGASTATE, last_width);
+ GEN_CHECK_OFF(VGASTATE, last_height);
+ GEN_CHECK_OFF(VGASTATE, last_scr_width);
+ GEN_CHECK_OFF(VGASTATE, last_scr_height);
+ GEN_CHECK_OFF(VGASTATE, last_bpp);
+ GEN_CHECK_OFF(VGASTATE, cursor_start);
+ GEN_CHECK_OFF(VGASTATE, cursor_end);
+ GEN_CHECK_OFF(VGASTATE, cursor_offset);
+ GEN_CHECK_OFF(VGASTATE, invalidated_y_table);
+ GEN_CHECK_OFF(VGASTATE, invalidated_y_table[1]);
+ GEN_CHECK_OFF(VGASTATE, invalidated_y_table[(VGA_MAX_HEIGHT / 32) - 1]);
+ GEN_CHECK_OFF(VGASTATE, last_palette);
+ GEN_CHECK_OFF(VGASTATE, last_palette[1]);
+ GEN_CHECK_OFF(VGASTATE, last_ch_attr);
+ GEN_CHECK_OFF(VGASTATE, last_ch_attr[CH_ATTR_SIZE - 1]);
+ GEN_CHECK_OFF(VGASTATE, u32Marker);
+ GEN_CHECK_OFF(VGASTATE, pDevInsRC);
+ GEN_CHECK_OFF(VGASTATE, vram_ptrRC);
+ GEN_CHECK_OFF(VGASTATE, pDevInsR3);
+#ifdef VBOX_WITH_HGSMI
+ GEN_CHECK_OFF(VGASTATE, pHGSMI);
+#endif
+#ifdef VBOX_WITH_VDMA
+ GEN_CHECK_OFF(VGASTATE, pVdma);
+#endif
+ GEN_CHECK_OFF(VGASTATE, IBase);
+ GEN_CHECK_OFF(VGASTATE, IPort);
+#if defined(VBOX_WITH_HGSMI) && defined(VBOX_WITH_VIDEOHWACCEL)
+ GEN_CHECK_OFF(VGASTATE, IVBVACallbacks);
+#endif
+ GEN_CHECK_OFF(VGASTATE, pDrvBase);
+ GEN_CHECK_OFF(VGASTATE, pDrv);
+ GEN_CHECK_OFF(VGASTATE, RefreshTimer);
+ GEN_CHECK_OFF(VGASTATE, pDevInsR0);
+#ifdef VBOX_WITH_VMSVGA
+ GEN_CHECK_OFF(VGASTATE, svga.pFIFOR3);
+ GEN_CHECK_OFF(VGASTATE, svga.pFIFOR0);
+ GEN_CHECK_OFF(VGASTATE, svga.pSvgaR3State);
+ GEN_CHECK_OFF(VGASTATE, svga.p3dState);
+ GEN_CHECK_OFF(VGASTATE, svga.pbVgaFrameBufferR3);
+ GEN_CHECK_OFF(VGASTATE, svga.GCPhysFIFO);
+ GEN_CHECK_OFF(VGASTATE, svga.cbFIFO);
+ GEN_CHECK_OFF(VGASTATE, svga.cbFIFOConfig);
+ GEN_CHECK_OFF(VGASTATE, svga.u32SVGAId);
+ GEN_CHECK_OFF(VGASTATE, svga.fConfigured);
+ GEN_CHECK_OFF(VGASTATE, svga.fBusy);
+ GEN_CHECK_OFF(VGASTATE, svga.fTraces);
+ GEN_CHECK_OFF(VGASTATE, svga.u32GuestId);
+ GEN_CHECK_OFF(VGASTATE, svga.cScratchRegion);
+ GEN_CHECK_OFF(VGASTATE, svga.u32IrqStatus);
+ GEN_CHECK_OFF(VGASTATE, svga.u32IrqMask);
+ GEN_CHECK_OFF(VGASTATE, svga.u32PitchLock);
+ GEN_CHECK_OFF(VGASTATE, svga.u32CurrentGMRId);
+ GEN_CHECK_OFF(VGASTATE, svga.u32RegCaps);
+ GEN_CHECK_OFF(VGASTATE, svga.u32IndexReg);
+ GEN_CHECK_OFF(VGASTATE, svga.hFIFORequestSem);
+ GEN_CHECK_OFF(VGASTATE, svga.hFIFOExtCmdSem);
+ GEN_CHECK_OFF(VGASTATE, svga.pFIFOIOThread);
+ GEN_CHECK_OFF(VGASTATE, svga.uWidth);
+ GEN_CHECK_OFF(VGASTATE, svga.uHeight);
+ GEN_CHECK_OFF(VGASTATE, svga.uBpp);
+ GEN_CHECK_OFF(VGASTATE, svga.cbScanline);
+ GEN_CHECK_OFF(VGASTATE, svga.u32MaxWidth);
+ GEN_CHECK_OFF(VGASTATE, svga.u32MaxHeight);
+ GEN_CHECK_OFF(VGASTATE, svga.viewport);
+ GEN_CHECK_OFF(VGASTATE, svga.u32ActionFlags);
+ GEN_CHECK_OFF(VGASTATE, svga.f3DEnabled);
+ GEN_CHECK_OFF(VGASTATE, svga.fVRAMTracking);
+ GEN_CHECK_OFF(VGASTATE, svga.u8FIFOExtCommand);
+ GEN_CHECK_OFF(VGASTATE, svga.fFifoExtCommandWakeup);
+ GEN_CHECK_OFF(VGASTATE, svga.au32ScratchRegion);
+ GEN_CHECK_OFF(VGASTATE, svga.StatRegBitsPerPixelWr);
+ GEN_CHECK_OFF(VGASTATE, svga.StatRegWriteOnlyRd);
+#endif
+ GEN_CHECK_OFF(VGASTATE, cMonitors);
+ GEN_CHECK_OFF(VGASTATE, cMilliesRefreshInterval);
+ GEN_CHECK_OFF(VGASTATE, au32DirtyBitmap);
+ GEN_CHECK_OFF(VGASTATE, au32DirtyBitmap[1]);
+ GEN_CHECK_OFF(VGASTATE, au32DirtyBitmap[(VGA_VRAM_MAX / GUEST_PAGE_SIZE / 32) - 1]);
+ GEN_CHECK_OFF(VGASTATE, fHasDirtyBits);
+ GEN_CHECK_OFF(VGASTATE, fLFBUpdated);
+ GEN_CHECK_OFF(VGASTATE, fGCEnabled);
+ GEN_CHECK_OFF(VGASTATE, fR0Enabled);
+ GEN_CHECK_OFF(VGASTATE, fRemappedVGA);
+ GEN_CHECK_OFF(VGASTATE, fRenderVRAM);
+ GEN_CHECK_OFF(VGASTATE, GCPhysVRAM);
+ GEN_CHECK_OFF(VGASTATE, CritSect);
+ GEN_CHECK_OFF(VGASTATE, Dev);
+ GEN_CHECK_OFF(VGASTATE, StatRZMemoryRead);
+ GEN_CHECK_OFF(VGASTATE, StatR3MemoryRead);
+ GEN_CHECK_OFF(VGASTATE, StatRZMemoryWrite);
+ GEN_CHECK_OFF(VGASTATE, StatR3MemoryWrite);
+#ifdef VBE_BYTEWISE_IO
+ GEN_CHECK_OFF(VGASTATE, fReadVBEData);
+ GEN_CHECK_OFF(VGASTATE, fWriteVBEData);
+ GEN_CHECK_OFF(VGASTATE, fReadVBEIndex);
+ GEN_CHECK_OFF(VGASTATE, fWriteVBEIndex);
+ GEN_CHECK_OFF(VGASTATE, cbWriteVBEData);
+ GEN_CHECK_OFF(VGASTATE, cbWriteVBEIndex);
+# ifdef VBE_NEW_DYN_LIST
+ GEN_CHECK_OFF(VGASTATE, cbWriteVBEExtraAddress);
+# endif
+#endif
+#ifdef VBE_NEW_DYN_LIST
+ GEN_CHECK_OFF(VGASTATE, pbVBEExtraData);
+ GEN_CHECK_OFF(VGASTATE, cbVBEExtraData);
+ GEN_CHECK_OFF(VGASTATE, u16VBEExtraAddress);
+#endif
+ GEN_CHECK_OFF(VGASTATE, pbLogo);
+ GEN_CHECK_OFF(VGASTATE, pszLogoFile);
+ GEN_CHECK_OFF(VGASTATE, pbLogoBitmap);
+ GEN_CHECK_OFF(VGASTATE, offLogoData);
+ GEN_CHECK_OFF(VGASTATE, cbLogo);
+ GEN_CHECK_OFF(VGASTATE, LogoCommand);
+ GEN_CHECK_OFF(VGASTATE, cxLogo);
+ GEN_CHECK_OFF(VGASTATE, cyLogo);
+ GEN_CHECK_OFF(VGASTATE, cLogoPlanes);
+ GEN_CHECK_OFF(VGASTATE, cLogoBits);
+ GEN_CHECK_OFF(VGASTATE, LogoCompression);
+ GEN_CHECK_OFF(VGASTATE, cLogoUsedColors);
+ GEN_CHECK_OFF(VGASTATE, cLogoPalEntries);
+ GEN_CHECK_OFF(VGASTATE, fLogoClearScreen);
+ GEN_CHECK_OFF(VGASTATE, au32LogoPalette);
+ GEN_CHECK_OFF(VGASTATE, pbVgaBios);
+ GEN_CHECK_OFF(VGASTATE, cbVgaBios);
+ GEN_CHECK_OFF(VGASTATE, pszVgaBiosFile);
+#ifdef VBOX_WITH_HGSMI
+ GEN_CHECK_OFF(VGASTATE, IOPortBase);
+#endif
+#ifdef VBOX_WITH_WDDM
+ GEN_CHECK_OFF(VGASTATE, fGuestCaps);
+#endif
+
+ /* Input/pckbd.c */
+ GEN_CHECK_SIZE(KBDSTATE);
+ GEN_CHECK_OFF(KBDSTATE, write_cmd);
+ GEN_CHECK_OFF(KBDSTATE, status);
+ GEN_CHECK_OFF(KBDSTATE, mode);
+ GEN_CHECK_OFF(KBDSTATE, pDevInsR3);
+ GEN_CHECK_OFF(KBDSTATE, pDevInsR0);
+ GEN_CHECK_OFF(KBDSTATE, pDevInsRC);
+ GEN_CHECK_SIZE(KbdKeyQ);
+ GEN_CHECK_OFF(KbdCmdQ, rpos);
+ GEN_CHECK_OFF(KbdCmdQ, wpos);
+ GEN_CHECK_OFF(KbdCmdQ, cUsed);
+ GEN_CHECK_OFF(KbdCmdQ, cSize);
+ GEN_CHECK_OFF(KbdCmdQ, abQueue);
+ GEN_CHECK_SIZE(KbdCmdQ);
+ /* Input/PS2K.c */
+ GEN_CHECK_SIZE(PS2K);
+ GEN_CHECK_OFF(PS2K, fScanning);
+ GEN_CHECK_OFF(PS2K, fNumLockOn);
+ GEN_CHECK_OFF(PS2K, u8ScanSet);
+ GEN_CHECK_OFF(PS2K, u8TypematicCfg);
+ GEN_CHECK_OFF(PS2K, enmTypematicState);
+ GEN_CHECK_OFF(PS2K, keyQ);
+ GEN_CHECK_OFF(PS2K, cmdQ);
+ GEN_CHECK_OFF(PS2K, uTypematicDelay);
+ GEN_CHECK_OFF(PS2K, fThrottleActive);
+ GEN_CHECK_OFF(PS2K, pKbdDelayTimerRC);
+ GEN_CHECK_OFF(PS2K, pKbdDelayTimerR3);
+ GEN_CHECK_OFF(PS2K, pKbdDelayTimerR0);
+ GEN_CHECK_OFF(PS2K, pKbdTypematicTimerRC);
+ GEN_CHECK_OFF(PS2K, pKbdTypematicTimerR3);
+ GEN_CHECK_OFF(PS2K, pKbdTypematicTimerR0);
+ GEN_CHECK_OFF(PS2K, pThrottleTimerRC);
+ GEN_CHECK_OFF(PS2K, pThrottleTimerR3);
+ GEN_CHECK_OFF(PS2K, pThrottleTimerR0);
+ GEN_CHECK_OFF(PS2K, pCritSectR3);
+ GEN_CHECK_OFF(PS2K, Keyboard.IBase);
+ GEN_CHECK_OFF(PS2K, Keyboard.IPort);
+ GEN_CHECK_OFF(PS2K, Keyboard.pDrvBase);
+ GEN_CHECK_OFF(PS2K, Keyboard.pDrv);
+ /* Input/PS2M.c */
+ GEN_CHECK_SIZE(PS2M);
+ GEN_CHECK_OFF(PS2M, u8State);
+ GEN_CHECK_OFF(PS2M, u8SampleRate);
+ GEN_CHECK_OFF(PS2M, u8Resolution);
+ GEN_CHECK_OFF(PS2M, u8CurrCmd);
+ GEN_CHECK_OFF(PS2M, fThrottleActive);
+ GEN_CHECK_OFF(PS2M, fDelayReset);
+ GEN_CHECK_OFF(PS2M, enmMode);
+ GEN_CHECK_OFF(PS2M, enmProtocol);
+ GEN_CHECK_OFF(PS2M, enmKnockState);
+ GEN_CHECK_OFF(PS2M, evtQ);
+ GEN_CHECK_OFF(PS2M, cmdQ);
+ GEN_CHECK_OFF(PS2M, iAccumX);
+ GEN_CHECK_OFF(PS2M, fAccumB);
+ GEN_CHECK_OFF(PS2M, fCurrB);
+ GEN_CHECK_OFF(PS2M, uThrottleDelay);
+ GEN_CHECK_OFF(PS2M, pCritSectR3);
+ GEN_CHECK_OFF(PS2M, pDelayTimerR3);
+ GEN_CHECK_OFF(PS2M, pThrottleTimerR3);
+ GEN_CHECK_OFF(PS2M, pDelayTimerRC);
+ GEN_CHECK_OFF(PS2M, pThrottleTimerRC);
+ GEN_CHECK_OFF(PS2M, pDelayTimerR0);
+ GEN_CHECK_OFF(PS2M, pThrottleTimerR0);
+ GEN_CHECK_OFF(PS2M, Mouse.IBase);
+ GEN_CHECK_OFF(PS2M, Mouse.IPort);
+ GEN_CHECK_OFF(PS2M, Mouse.pDrvBase);
+ GEN_CHECK_OFF(PS2M, Mouse.pDrv);
+
+ /* Network/DevPCNet.cpp */
+ GEN_CHECK_SIZE(PCNETSTATE);
+ GEN_CHECK_OFF(PCNETSTATE, PciDev);
+#ifndef PCNET_NO_POLLING
+ GEN_CHECK_OFF(PCNETSTATE, pTimerPollR3);
+ GEN_CHECK_OFF(PCNETSTATE, pTimerPollR0);
+ GEN_CHECK_OFF(PCNETSTATE, pTimerPollRC);
+#endif
+ GEN_CHECK_OFF(PCNETSTATE, pTimerSoftIntR3);
+ GEN_CHECK_OFF(PCNETSTATE, pTimerSoftIntR0);
+ GEN_CHECK_OFF(PCNETSTATE, pTimerSoftIntRC);
+ GEN_CHECK_OFF(PCNETSTATE, u32RAP);
+ GEN_CHECK_OFF(PCNETSTATE, iISR);
+ GEN_CHECK_OFF(PCNETSTATE, u32Lnkst);
+ GEN_CHECK_OFF(PCNETSTATE, GCRDRA);
+ GEN_CHECK_OFF(PCNETSTATE, GCTDRA);
+ GEN_CHECK_OFF(PCNETSTATE, aPROM);
+ GEN_CHECK_OFF(PCNETSTATE, aPROM[1]);
+ GEN_CHECK_OFF(PCNETSTATE, aCSR);
+ GEN_CHECK_OFF(PCNETSTATE, aCSR[1]);
+ GEN_CHECK_OFF(PCNETSTATE, aCSR[CSR_MAX_REG - 1]);
+ GEN_CHECK_OFF(PCNETSTATE, aBCR);
+ GEN_CHECK_OFF(PCNETSTATE, aBCR[1]);
+ GEN_CHECK_OFF(PCNETSTATE, aBCR[BCR_MAX_RAP - 1]);
+ GEN_CHECK_OFF(PCNETSTATE, aMII);
+ GEN_CHECK_OFF(PCNETSTATE, aMII[1]);
+ GEN_CHECK_OFF(PCNETSTATE, aMII[MII_MAX_REG - 1]);
+ GEN_CHECK_OFF(PCNETSTATE, u16CSR0LastSeenByGuest);
+ GEN_CHECK_OFF(PCNETSTATE, u64LastPoll);
+ GEN_CHECK_OFF(PCNETSTATE, abLoopBuf);
+ GEN_CHECK_OFF(PCNETSTATE, abRecvBuf);
+ GEN_CHECK_OFF(PCNETSTATE, iLog2DescSize);
+ GEN_CHECK_OFF(PCNETSTATE, GCUpperPhys);
+ GEN_CHECK_OFF(PCNETSTATE, pXmitQueueR3);
+ GEN_CHECK_OFF(PCNETSTATE, pXmitQueueR0);
+ GEN_CHECK_OFF(PCNETSTATE, pXmitQueueRC);
+ GEN_CHECK_OFF(PCNETSTATE, pCanRxQueueR3);
+ GEN_CHECK_OFF(PCNETSTATE, pCanRxQueueR0);
+ GEN_CHECK_OFF(PCNETSTATE, pCanRxQueueRC);
+ GEN_CHECK_OFF(PCNETSTATE, pTimerRestore);
+ GEN_CHECK_OFF(PCNETSTATE, pDevInsR3);
+ GEN_CHECK_OFF(PCNETSTATE, pDevInsR0);
+ GEN_CHECK_OFF(PCNETSTATE, pDevInsRC);
+ GEN_CHECK_OFF(PCNETSTATE, pDrvR3);
+ GEN_CHECK_OFF(PCNETSTATE, pDrvBase);
+ GEN_CHECK_OFF(PCNETSTATE, IBase);
+ GEN_CHECK_OFF(PCNETSTATE, INetworkDown);
+ GEN_CHECK_OFF(PCNETSTATE, INetworkConfig);
+ GEN_CHECK_OFF(PCNETSTATE, MMIOBase);
+ GEN_CHECK_OFF(PCNETSTATE, IOPortBase);
+ GEN_CHECK_OFF(PCNETSTATE, fLinkUp);
+ GEN_CHECK_OFF(PCNETSTATE, fLinkTempDown);
+ GEN_CHECK_OFF(PCNETSTATE, cLinkDownReported);
+ GEN_CHECK_OFF(PCNETSTATE, MacConfigured);
+ GEN_CHECK_OFF(PCNETSTATE, Led);
+ GEN_CHECK_OFF(PCNETSTATE, ILeds);
+ GEN_CHECK_OFF(PCNETSTATE, pLedsConnector);
+ GEN_CHECK_OFF(PCNETSTATE, CritSect);
+#ifdef PCNET_NO_POLLING
+ GEN_CHECK_OFF(PCNETSTATE, TDRAPhysOld);
+ GEN_CHECK_OFF(PCNETSTATE, cbTDRAOld);
+ GEN_CHECK_OFF(PCNETSTATE, RDRAPhysOld);
+ GEN_CHECK_OFF(PCNETSTATE, cbRDRAOld);
+ GEN_CHECK_OFF(PCNETSTATE, pfnEMInterpretInstructionGC
+ GEN_CHECK_OFF(PCNETSTATE, pfnEMInterpretInstructionR0
+#endif
+ GEN_CHECK_OFF(PCNETSTATE, fGCEnabled);
+ GEN_CHECK_OFF(PCNETSTATE, fR0Enabled);
+ GEN_CHECK_OFF(PCNETSTATE, uDevType);
+ GEN_CHECK_OFF(PCNETSTATE, StatReceiveBytes);
+ GEN_CHECK_OFF(PCNETSTATE, StatTransmitBytes);
+#ifdef VBOX_WITH_STATISTICS
+ GEN_CHECK_OFF(PCNETSTATE, StatMMIOReadR3);
+ GEN_CHECK_OFF(PCNETSTATE, StatMMIOReadRZ);
+ GEN_CHECK_OFF(PCNETSTATE, StatMIIReads);
+# ifdef PCNET_NO_POLLING
+ GEN_CHECK_OFF(PCNETSTATE, StatRCVRingWrite);
+ GEN_CHECK_OFF(PCNETSTATE, StatRingWriteOutsideRangeR3);
+# endif
+#endif
+
+ /* PC/DevACPI.cpp */
+ GEN_CHECK_SIZE(ACPIState);
+ GEN_CHECK_OFF(ACPIState, dev);
+ GEN_CHECK_OFF(ACPIState, pm1a_en);
+ GEN_CHECK_OFF(ACPIState, pm1a_sts);
+ GEN_CHECK_OFF(ACPIState, pm1a_ctl);
+ GEN_CHECK_OFF(ACPIState, u64PmTimerInitial);
+ GEN_CHECK_OFF(ACPIState, pPmTimerR3);
+ GEN_CHECK_OFF(ACPIState, pPmTimerR0);
+ GEN_CHECK_OFF(ACPIState, pPmTimerRC);
+ GEN_CHECK_OFF(ACPIState, uPmTimerVal);
+ GEN_CHECK_OFF(ACPIState, gpe0_en);
+ GEN_CHECK_OFF(ACPIState, gpe0_sts);
+ GEN_CHECK_OFF(ACPIState, uBatteryIndex);
+ GEN_CHECK_OFF(ACPIState, au8BatteryInfo);
+ GEN_CHECK_OFF(ACPIState, uSystemInfoIndex);
+ GEN_CHECK_OFF(ACPIState, u64RamSize);
+ GEN_CHECK_OFF(ACPIState, uSleepState);
+ GEN_CHECK_OFF(ACPIState, au8RSDPPage);
+ GEN_CHECK_OFF(ACPIState, u8IndexShift);
+ GEN_CHECK_OFF(ACPIState, u8UseIOApic);
+ GEN_CHECK_OFF(ACPIState, fUseFdc);
+ GEN_CHECK_OFF(ACPIState, fUseHpet);
+ GEN_CHECK_OFF(ACPIState, fUseSmc);
+ GEN_CHECK_OFF(ACPIState, CpuSetAttached);
+ GEN_CHECK_OFF(ACPIState, idCpuLockCheck);
+ GEN_CHECK_OFF(ACPIState, CpuSetLocked);
+ GEN_CHECK_OFF(ACPIState, u32CpuEventType);
+ GEN_CHECK_OFF(ACPIState, u32CpuEvent);
+ GEN_CHECK_OFF(ACPIState, fCpuHotPlug);
+ GEN_CHECK_OFF(ACPIState, u32NicPciAddress);
+ GEN_CHECK_OFF(ACPIState, u32HbcPciAddress);
+ GEN_CHECK_OFF(ACPIState, u32IommuPciAddress);
+ GEN_CHECK_OFF(ACPIState, u32SbIoApicPciAddress);
+ GEN_CHECK_OFF(ACPIState, u64PciConfigMMioAddress);
+ GEN_CHECK_OFF(ACPIState, IBase);
+ GEN_CHECK_OFF(ACPIState, IACPIPort);
+ GEN_CHECK_OFF(ACPIState, pDevInsR3);
+ GEN_CHECK_OFF(ACPIState, pDevInsR0);
+ GEN_CHECK_OFF(ACPIState, pDrvBase);
+ GEN_CHECK_OFF(ACPIState, pDrv);
+ GEN_CHECK_OFF(ACPIState, u16SMBusSlvDat);
+
+ /* PC/DevPIC.cpp */
+ GEN_CHECK_SIZE(PICSTATE);
+ GEN_CHECK_OFF(PICSTATE, last_irr);
+ GEN_CHECK_OFF(PICSTATE, irr);
+ GEN_CHECK_OFF(PICSTATE, imr);
+ GEN_CHECK_OFF(PICSTATE, isr);
+ GEN_CHECK_OFF(PICSTATE, priority_add);
+ GEN_CHECK_OFF(PICSTATE, irq_base);
+ GEN_CHECK_OFF(PICSTATE, read_reg_select);
+ GEN_CHECK_OFF(PICSTATE, poll);
+ GEN_CHECK_OFF(PICSTATE, special_mask);
+ GEN_CHECK_OFF(PICSTATE, init_state);
+ GEN_CHECK_OFF(PICSTATE, auto_eoi);
+ GEN_CHECK_OFF(PICSTATE, rotate_on_auto_eoi);
+ GEN_CHECK_OFF(PICSTATE, special_fully_nested_mode);
+ GEN_CHECK_OFF(PICSTATE, init4);
+ GEN_CHECK_OFF(PICSTATE, elcr);
+ GEN_CHECK_OFF(PICSTATE, elcr_mask);
+ GEN_CHECK_OFF(PICSTATE, pDevInsR3);
+ GEN_CHECK_OFF(PICSTATE, pDevInsR0);
+ GEN_CHECK_OFF(PICSTATE, pDevInsRC);
+ GEN_CHECK_OFF(PICSTATE, idxPic);
+ GEN_CHECK_OFF(PICSTATE, auTags);
+
+ GEN_CHECK_SIZE(DEVPIC);
+ GEN_CHECK_OFF(DEVPIC, aPics);
+ GEN_CHECK_OFF(DEVPIC, aPics[1]);
+ GEN_CHECK_OFF(DEVPIC, pDevInsR3);
+ GEN_CHECK_OFF(DEVPIC, pDevInsR0);
+ GEN_CHECK_OFF(DEVPIC, pDevInsRC);
+ GEN_CHECK_OFF(DEVPIC, pPicHlpR3);
+ GEN_CHECK_OFF(DEVPIC, pPicHlpR0);
+ GEN_CHECK_OFF(DEVPIC, pPicHlpRC);
+#ifdef VBOX_WITH_STATISTICS
+ GEN_CHECK_OFF(DEVPIC, StatSetIrqGC);
+ GEN_CHECK_OFF(DEVPIC, StatClearedActiveSlaveIRQ);
+#endif
+
+ /* PC/DevPit-i8254.cpp */
+ GEN_CHECK_SIZE(DMAState);
+ GEN_CHECK_OFF(DMAState, DMAC);
+ GEN_CHECK_OFF(DMAState, DMAC[0].ChState[0]);
+ GEN_CHECK_OFF(DMAState, DMAC[0].ChState[1]);
+ GEN_CHECK_OFF(DMAState, DMAC[0].u8Mask);
+ GEN_CHECK_OFF(DMAState, DMAC[1].ChState[0]);
+ GEN_CHECK_OFF(DMAState, DMAC[1].ChState[1]);
+ GEN_CHECK_OFF(DMAState, DMAC[1].u8Mask);
+
+ /* PC/DevPit-i8254.cpp */
+ GEN_CHECK_SIZE(PITCHANNEL);
+ GEN_CHECK_OFF(PITCHANNEL, pPitR3);
+ GEN_CHECK_OFF(PITCHANNEL, pTimerR3);
+ GEN_CHECK_OFF(PITCHANNEL, pPitR0);
+ GEN_CHECK_OFF(PITCHANNEL, pTimerR0);
+ GEN_CHECK_OFF(PITCHANNEL, pPitRC);
+ GEN_CHECK_OFF(PITCHANNEL, pTimerRC);
+ GEN_CHECK_OFF(PITCHANNEL, u64ReloadTS);
+ GEN_CHECK_OFF(PITCHANNEL, u64NextTS);
+ GEN_CHECK_OFF(PITCHANNEL, count_load_time);
+ GEN_CHECK_OFF(PITCHANNEL, next_transition_time);
+ GEN_CHECK_OFF(PITCHANNEL, irq);
+ GEN_CHECK_OFF(PITCHANNEL, cRelLogEntries);
+ GEN_CHECK_OFF(PITCHANNEL, count);
+ GEN_CHECK_OFF(PITCHANNEL, latched_count);
+ GEN_CHECK_OFF(PITCHANNEL, count_latched);
+ GEN_CHECK_OFF(PITCHANNEL, status_latched);
+ GEN_CHECK_OFF(PITCHANNEL, status);
+ GEN_CHECK_OFF(PITCHANNEL, read_state);
+ GEN_CHECK_OFF(PITCHANNEL, write_state);
+ GEN_CHECK_OFF(PITCHANNEL, write_latch);
+ GEN_CHECK_OFF(PITCHANNEL, rw_mode);
+ GEN_CHECK_OFF(PITCHANNEL, mode);
+ GEN_CHECK_OFF(PITCHANNEL, bcd);
+ GEN_CHECK_OFF(PITCHANNEL, gate);
+ GEN_CHECK_SIZE(PITSTATE);
+ GEN_CHECK_OFF(PITSTATE, channels);
+ GEN_CHECK_OFF(PITSTATE, channels[1]);
+ GEN_CHECK_OFF(PITSTATE, speaker_data_on);
+// GEN_CHECK_OFF(PITSTATE, dummy_refresh_clock);
+ GEN_CHECK_OFF(PITSTATE, IOPortBaseCfg);
+ GEN_CHECK_OFF(PITSTATE, fSpeakerCfg);
+ GEN_CHECK_OFF(PITSTATE, pDevIns);
+ GEN_CHECK_OFF(PITSTATE, StatPITIrq);
+ GEN_CHECK_OFF(PITSTATE, StatPITHandler);
+
+ /* PC/DevRTC.cpp */
+ GEN_CHECK_SIZE(RTCSTATE);
+ GEN_CHECK_OFF(RTCSTATE, cmos_data);
+ GEN_CHECK_OFF(RTCSTATE, cmos_data[1]);
+ GEN_CHECK_OFF(RTCSTATE, cmos_index);
+ GEN_CHECK_OFF(RTCSTATE, current_tm);
+ GEN_CHECK_OFF(RTCSTATE, current_tm.tm_sec);
+ GEN_CHECK_OFF(RTCSTATE, current_tm.tm_min);
+ GEN_CHECK_OFF(RTCSTATE, current_tm.tm_hour);
+ GEN_CHECK_OFF(RTCSTATE, current_tm.tm_mday);
+ GEN_CHECK_OFF(RTCSTATE, current_tm.tm_mon);
+ GEN_CHECK_OFF(RTCSTATE, current_tm.tm_year);
+ GEN_CHECK_OFF(RTCSTATE, current_tm.tm_wday);
+ GEN_CHECK_OFF(RTCSTATE, current_tm.tm_yday);
+ GEN_CHECK_OFF(RTCSTATE, irq);
+ GEN_CHECK_OFF(RTCSTATE, fUTC);
+ GEN_CHECK_OFF(RTCSTATE, IOPortBase);
+ GEN_CHECK_OFF(RTCSTATE, pPeriodicTimerR0);
+ GEN_CHECK_OFF(RTCSTATE, pPeriodicTimerR3);
+ GEN_CHECK_OFF(RTCSTATE, pPeriodicTimerRC);
+ GEN_CHECK_OFF(RTCSTATE, next_periodic_time);
+ GEN_CHECK_OFF(RTCSTATE, next_second_time);
+ GEN_CHECK_OFF(RTCSTATE, pSecondTimerR0);
+ GEN_CHECK_OFF(RTCSTATE, pSecondTimerR3);
+ GEN_CHECK_OFF(RTCSTATE, pSecondTimerRC);
+ GEN_CHECK_OFF(RTCSTATE, pSecondTimer2R0);
+ GEN_CHECK_OFF(RTCSTATE, pSecondTimer2R3);
+ GEN_CHECK_OFF(RTCSTATE, pSecondTimer2RC);
+ GEN_CHECK_OFF(RTCSTATE, pDevInsR0);
+ GEN_CHECK_OFF(RTCSTATE, pDevInsR3);
+ GEN_CHECK_OFF(RTCSTATE, pDevInsRC);
+ GEN_CHECK_OFF(RTCSTATE, RtcReg);
+ GEN_CHECK_OFF(RTCSTATE, pRtcHlpR3);
+ GEN_CHECK_OFF(RTCSTATE, cRelLogEntries);
+ GEN_CHECK_OFF(RTCSTATE, CurLogPeriod);
+ GEN_CHECK_OFF(RTCSTATE, CurHintPeriod);
+
+ GEN_CHECK_SIZE(APIC);
+ GEN_CHECK_OFF(APIC, pApicDevR0);
+ GEN_CHECK_OFF(APIC, pApicDevR3);
+ GEN_CHECK_OFF(APIC, pApicDevRC);
+ GEN_CHECK_OFF(APIC, HCPhysApicPib);
+ GEN_CHECK_OFF(APIC, pvApicPibR0);
+ GEN_CHECK_OFF(APIC, pvApicPibR3);
+ GEN_CHECK_OFF(APIC, pvApicPibRC);
+ GEN_CHECK_OFF(APIC, cbApicPib);
+ GEN_CHECK_OFF(APIC, fVirtApicRegsEnabled);
+ GEN_CHECK_OFF(APIC, fPostedIntrsEnabled);
+ GEN_CHECK_OFF(APIC, fSupportsTscDeadline);
+ GEN_CHECK_OFF(APIC, fIoApicPresent);
+ GEN_CHECK_OFF(APIC, fRZEnabled);
+ GEN_CHECK_OFF(APIC, enmMaxMode);
+
+ GEN_CHECK_SIZE(APICCPU);
+ GEN_CHECK_OFF(APICCPU, pvApicPageR0);
+ GEN_CHECK_OFF(APICCPU, pvApicPageR3);
+ GEN_CHECK_OFF(APICCPU, pvApicPageRC);
+ GEN_CHECK_OFF(APICCPU, cbApicPage);
+ GEN_CHECK_OFF(APICCPU, uEsrInternal);
+ GEN_CHECK_OFF(APICCPU, uApicBaseMsr);
+ GEN_CHECK_OFF(APICCPU, HCPhysApicPib);
+ GEN_CHECK_OFF(APICCPU, pvApicPibR0);
+ GEN_CHECK_OFF(APICCPU, pvApicPibR3);
+ GEN_CHECK_OFF(APICCPU, pvApicPibRC);
+ GEN_CHECK_OFF(APICCPU, ApicPibLevel);
+ GEN_CHECK_OFF(APICCPU, pTimerR0);
+ GEN_CHECK_OFF(APICCPU, pTimerR3);
+ GEN_CHECK_OFF(APICCPU, pTimerRC);
+ GEN_CHECK_OFF(APICCPU, TimerCritSect);
+ GEN_CHECK_OFF(APICCPU, u64TimerInitial);
+ GEN_CHECK_OFF(APICCPU, uHintedTimerInitialCount);
+ GEN_CHECK_OFF(APICCPU, uHintedTimerShift);
+# ifdef VBOX_WITH_STATISTICS
+ GEN_CHECK_OFF(APICCPU, StatMmioReadRZ);
+ GEN_CHECK_OFF(APICCPU, StatMmioReadR3);
+ GEN_CHECK_OFF(APICCPU, StatMmioWriteRZ);
+ GEN_CHECK_OFF(APICCPU, StatMmioWriteR3);
+ GEN_CHECK_OFF(APICCPU, StatMsrReadRZ);
+ GEN_CHECK_OFF(APICCPU, StatMsrReadR3);
+ GEN_CHECK_OFF(APICCPU, StatMsrWriteRZ);
+ GEN_CHECK_OFF(APICCPU, StatMsrWriteR3);
+ GEN_CHECK_OFF(APICCPU, StatUpdatePendingIntrs);
+ GEN_CHECK_OFF(APICCPU, StatPostIntr);
+ GEN_CHECK_OFF(APICCPU, StatPostIntrAlreadyPending);
+ GEN_CHECK_OFF(APICCPU, StatTimerCallback);
+ GEN_CHECK_OFF(APICCPU, StatTprWrite);
+ GEN_CHECK_OFF(APICCPU, StatTprRead);
+ GEN_CHECK_OFF(APICCPU, StatEoiWrite);
+ GEN_CHECK_OFF(APICCPU, StatMaskedByTpr);
+ GEN_CHECK_OFF(APICCPU, StatMaskedByPpr);
+ GEN_CHECK_OFF(APICCPU, StatTimerIcrWrite);
+ GEN_CHECK_OFF(APICCPU, StatIcrLoWrite);
+ GEN_CHECK_OFF(APICCPU, StatIcrHiWrite);
+ GEN_CHECK_OFF(APICCPU, StatIcrFullWrite);
+# endif /* VBOX_WITH_STATISTICS */
+
+ /* PC/DevIoApic.cpp */
+ GEN_CHECK_SIZE(IOAPIC);
+ GEN_CHECK_OFF(IOAPIC, pDevInsR3);
+ GEN_CHECK_OFF(IOAPIC, pIoApicHlpR3);
+ GEN_CHECK_OFF(IOAPIC, pDevInsR0);
+ GEN_CHECK_OFF(IOAPIC, pIoApicHlpR0);
+ GEN_CHECK_OFF(IOAPIC, pDevInsRC);
+ GEN_CHECK_OFF(IOAPIC, pIoApicHlpRC);
+ GEN_CHECK_OFF(IOAPIC, u8Id);
+ GEN_CHECK_OFF(IOAPIC, u8Index);
+ GEN_CHECK_OFF(IOAPIC, cCpus);
+ GEN_CHECK_OFF(IOAPIC, au64RedirTable);
+ GEN_CHECK_OFF(IOAPIC, uIrr);
+# ifdef VBOX_WITH_STATISTICS
+ GEN_CHECK_OFF(IOAPIC, StatMmioReadRZ);
+ GEN_CHECK_OFF(IOAPIC, StatMmioReadR3);
+ GEN_CHECK_OFF(IOAPIC, StatMmioWriteRZ);
+ GEN_CHECK_OFF(IOAPIC, StatMmioWriteR3);
+ GEN_CHECK_OFF(IOAPIC, StatSetIrqRZ);
+ GEN_CHECK_OFF(IOAPIC, StatSetIrqR3);
+ GEN_CHECK_OFF(IOAPIC, StatSetEoiRZ);
+ GEN_CHECK_OFF(IOAPIC, StatSetEoiR3);
+# endif
+
+ /* Storage/DevATA.cpp */
+ GEN_CHECK_SIZE(BMDMAState);
+ GEN_CHECK_OFF(BMDMAState, u8Cmd);
+ GEN_CHECK_OFF(BMDMAState, u8Status);
+ GEN_CHECK_OFF(BMDMAState, GCPhysAddr);
+ GEN_CHECK_SIZE(BMDMADesc);
+ GEN_CHECK_OFF(BMDMADesc, GCPhysBuffer);
+ GEN_CHECK_OFF(BMDMADesc, cbBuffer);
+ GEN_CHECK_SIZE(ATADevState);
+ GEN_CHECK_OFF(ATADevState, fLBA48);
+ GEN_CHECK_OFF(ATADevState, fATAPI);
+ GEN_CHECK_OFF(ATADevState, fIrqPending);
+ GEN_CHECK_OFF(ATADevState, cMultSectors);
+ GEN_CHECK_OFF(ATADevState, cbSector);
+ GEN_CHECK_OFF(ATADevState, PCHSGeometry.cCylinders);
+ GEN_CHECK_OFF(ATADevState, PCHSGeometry.cHeads);
+ GEN_CHECK_OFF(ATADevState, PCHSGeometry.cSectors);
+ GEN_CHECK_OFF(ATADevState, cSectorsPerIRQ);
+ GEN_CHECK_OFF(ATADevState, cTotalSectors);
+ GEN_CHECK_OFF(ATADevState, uATARegFeature);
+ GEN_CHECK_OFF(ATADevState, uATARegFeatureHOB);
+ GEN_CHECK_OFF(ATADevState, uATARegError);
+ GEN_CHECK_OFF(ATADevState, uATARegNSector);
+ GEN_CHECK_OFF(ATADevState, uATARegNSectorHOB);
+ GEN_CHECK_OFF(ATADevState, uATARegSector);
+ GEN_CHECK_OFF(ATADevState, uATARegSectorHOB);
+ GEN_CHECK_OFF(ATADevState, uATARegLCyl);
+ GEN_CHECK_OFF(ATADevState, uATARegLCylHOB);
+ GEN_CHECK_OFF(ATADevState, uATARegHCyl);
+ GEN_CHECK_OFF(ATADevState, uATARegHCylHOB);
+ GEN_CHECK_OFF(ATADevState, uATARegSelect);
+ GEN_CHECK_OFF(ATADevState, uATARegStatus);
+ GEN_CHECK_OFF(ATADevState, uATARegCommand);
+ GEN_CHECK_OFF(ATADevState, uATARegDevCtl);
+ GEN_CHECK_OFF(ATADevState, uATATransferMode);
+ GEN_CHECK_OFF(ATADevState, uTxDir);
+ GEN_CHECK_OFF(ATADevState, iBeginTransfer);
+ GEN_CHECK_OFF(ATADevState, iSourceSink);
+ GEN_CHECK_OFF(ATADevState, fDMA);
+ GEN_CHECK_OFF(ATADevState, fATAPITransfer);
+ GEN_CHECK_OFF(ATADevState, cbTotalTransfer);
+ GEN_CHECK_OFF(ATADevState, cbElementaryTransfer);
+ GEN_CHECK_OFF(ATADevState, iIOBufferCur);
+ GEN_CHECK_OFF(ATADevState, iIOBufferEnd);
+ GEN_CHECK_OFF(ATADevState, iIOBufferPIODataStart);
+ GEN_CHECK_OFF(ATADevState, iIOBufferPIODataEnd);
+ GEN_CHECK_OFF(ATADevState, iATAPILBA);
+ GEN_CHECK_OFF(ATADevState, cbATAPISector);
+ GEN_CHECK_OFF(ATADevState, aATAPICmd);
+ GEN_CHECK_OFF(ATADevState, aATAPICmd[ATAPI_PACKET_SIZE - 1]);
+ GEN_CHECK_OFF(ATADevState, abATAPISense);
+ GEN_CHECK_OFF(ATADevState, abATAPISense[ATAPI_SENSE_SIZE - 1]);
+ GEN_CHECK_OFF(ATADevState, cNotifiedMediaChange);
+ GEN_CHECK_OFF(ATADevState, MediaEventStatus);
+ GEN_CHECK_OFF(ATADevState, MediaTrackType);
+ GEN_CHECK_OFF(ATADevState, Led);
+ GEN_CHECK_OFF(ATADevState, cbIOBuffer);
+ GEN_CHECK_OFF(ATADevState, pbIOBufferR3);
+ GEN_CHECK_OFF(ATADevState, pbIOBufferR0);
+ GEN_CHECK_OFF(ATADevState, pbIOBufferRC);
+ GEN_CHECK_OFF(ATADevState, StatATADMA);
+ GEN_CHECK_OFF(ATADevState, StatATAPIO);
+ GEN_CHECK_OFF(ATADevState, StatATAPIDMA);
+ GEN_CHECK_OFF(ATADevState, StatATAPIPIO);
+ GEN_CHECK_OFF(ATADevState, StatReads);
+ GEN_CHECK_OFF(ATADevState, StatBytesRead);
+ GEN_CHECK_OFF(ATADevState, StatWrites);
+ GEN_CHECK_OFF(ATADevState, StatBytesWritten);
+ GEN_CHECK_OFF(ATADevState, StatFlushes);
+ GEN_CHECK_OFF(ATADevState, fATAPIPassthrough);
+ GEN_CHECK_OFF(ATADevState, fOverwriteInquiry);
+ GEN_CHECK_OFF(ATADevState, cErrors);
+ GEN_CHECK_OFF(ATADevState, pDrvBase);
+ GEN_CHECK_OFF(ATADevState, pDrvMedia);
+ GEN_CHECK_OFF(ATADevState, pDrvMount);
+ GEN_CHECK_OFF(ATADevState, IBase);
+ GEN_CHECK_OFF(ATADevState, IPort);
+ GEN_CHECK_OFF(ATADevState, IMountNotify);
+ GEN_CHECK_OFF(ATADevState, iLUN);
+ GEN_CHECK_OFF(ATADevState, pDevInsR3);
+ GEN_CHECK_OFF(ATADevState, pDevInsR0);
+ GEN_CHECK_OFF(ATADevState, pDevInsRC);
+ GEN_CHECK_OFF(ATADevState, pControllerR3);
+ GEN_CHECK_OFF(ATADevState, pControllerR0);
+ GEN_CHECK_OFF(ATADevState, pControllerRC);
+ GEN_CHECK_OFF(ATADevState, szSerialNumber);
+ GEN_CHECK_OFF(ATADevState, szSerialNumber[ATA_SERIAL_NUMBER_LENGTH]);
+ GEN_CHECK_OFF(ATADevState, szFirmwareRevision);
+ GEN_CHECK_OFF(ATADevState, szFirmwareRevision[ATA_FIRMWARE_REVISION_LENGTH]);
+ GEN_CHECK_OFF(ATADevState, szModelNumber);
+ GEN_CHECK_OFF(ATADevState, szModelNumber[ATA_MODEL_NUMBER_LENGTH]);
+ GEN_CHECK_OFF(ATADevState, szInquiryVendorId);
+ GEN_CHECK_OFF(ATADevState, szInquiryVendorId[SCSI_INQUIRY_VENDOR_ID_LENGTH]);
+ GEN_CHECK_OFF(ATADevState, szInquiryProductId);
+ GEN_CHECK_OFF(ATADevState, szInquiryProductId[SCSI_INQUIRY_PRODUCT_ID_LENGTH]);
+ GEN_CHECK_OFF(ATADevState, szInquiryRevision);
+ GEN_CHECK_OFF(ATADevState, szInquiryRevision[SCSI_INQUIRY_REVISION_LENGTH]);
+ GEN_CHECK_OFF(ATADevState, pTrackList);
+ GEN_CHECK_SIZE(ATATransferRequest);
+ GEN_CHECK_OFF(ATATransferRequest, iIf);
+ GEN_CHECK_OFF(ATATransferRequest, iBeginTransfer);
+ GEN_CHECK_OFF(ATATransferRequest, iSourceSink);
+ GEN_CHECK_OFF(ATATransferRequest, cbTotalTransfer);
+ GEN_CHECK_OFF(ATATransferRequest, uTxDir);
+ GEN_CHECK_SIZE(ATAAbortRequest);
+ GEN_CHECK_OFF(ATAAbortRequest, iIf);
+ GEN_CHECK_OFF(ATAAbortRequest, fResetDrive);
+ GEN_CHECK_SIZE(ATARequest);
+ GEN_CHECK_OFF(ATARequest, ReqType);
+ GEN_CHECK_OFF(ATARequest, u);
+ GEN_CHECK_OFF(ATARequest, u.t);
+ GEN_CHECK_OFF(ATARequest, u.a);
+ GEN_CHECK_SIZE(ATACONTROLLER);
+ GEN_CHECK_OFF(ATACONTROLLER, IOPortBase1);
+ GEN_CHECK_OFF(ATACONTROLLER, IOPortBase2);
+ GEN_CHECK_OFF(ATACONTROLLER, irq);
+ GEN_CHECK_OFF(ATACONTROLLER, lock);
+ GEN_CHECK_OFF(ATACONTROLLER, iSelectedIf);
+ GEN_CHECK_OFF(ATACONTROLLER, iAIOIf);
+ GEN_CHECK_OFF(ATACONTROLLER, uAsyncIOState);
+ GEN_CHECK_OFF(ATACONTROLLER, fChainedTransfer);
+ GEN_CHECK_OFF(ATACONTROLLER, fReset);
+ GEN_CHECK_OFF(ATACONTROLLER, fRedo);
+ GEN_CHECK_OFF(ATACONTROLLER, fRedoIdle);
+ GEN_CHECK_OFF(ATACONTROLLER, fRedoDMALastDesc);
+ GEN_CHECK_OFF(ATACONTROLLER, BmDma);
+ GEN_CHECK_OFF(ATACONTROLLER, GCPhysFirstDMADesc);
+ GEN_CHECK_OFF(ATACONTROLLER, GCPhysLastDMADesc);
+ GEN_CHECK_OFF(ATACONTROLLER, GCPhysRedoDMABuffer);
+ GEN_CHECK_OFF(ATACONTROLLER, cbRedoDMABuffer);
+ GEN_CHECK_OFF(ATACONTROLLER, aIfs);
+ GEN_CHECK_OFF(ATACONTROLLER, aIfs[1]);
+ GEN_CHECK_OFF(ATACONTROLLER, pDevInsR3);
+ GEN_CHECK_OFF(ATACONTROLLER, pDevInsR0);
+ GEN_CHECK_OFF(ATACONTROLLER, pDevInsRC);
+ GEN_CHECK_OFF(ATACONTROLLER, fShutdown);
+ GEN_CHECK_OFF(ATACONTROLLER, AsyncIOThread);
+ GEN_CHECK_OFF(ATACONTROLLER, hAsyncIOSem);
+ GEN_CHECK_OFF(ATACONTROLLER, aAsyncIORequests[4]);
+ GEN_CHECK_OFF(ATACONTROLLER, AsyncIOReqHead);
+ GEN_CHECK_OFF(ATACONTROLLER, AsyncIOReqTail);
+ GEN_CHECK_OFF(ATACONTROLLER, AsyncIORequestLock);
+ GEN_CHECK_OFF(ATACONTROLLER, SuspendIOSem);
+ GEN_CHECK_OFF(ATACONTROLLER, fSignalIdle);
+ GEN_CHECK_OFF(ATACONTROLLER, DelayIRQMillies);
+ GEN_CHECK_OFF(ATACONTROLLER, u64ResetTime);
+ GEN_CHECK_OFF(ATACONTROLLER, StatAsyncOps);
+ GEN_CHECK_OFF(ATACONTROLLER, StatAsyncMinWait);
+ GEN_CHECK_OFF(ATACONTROLLER, StatAsyncMaxWait);
+ GEN_CHECK_OFF(ATACONTROLLER, StatAsyncTimeUS);
+ GEN_CHECK_OFF(ATACONTROLLER, StatAsyncTime);
+ GEN_CHECK_OFF(ATACONTROLLER, StatLockWait);
+ GEN_CHECK_SIZE(PCIATAState);
+ GEN_CHECK_OFF(PCIATAState, dev);
+ GEN_CHECK_OFF(PCIATAState, aCts);
+ GEN_CHECK_OFF(PCIATAState, aCts[1]);
+ GEN_CHECK_OFF(PCIATAState, pDevIns);
+ GEN_CHECK_OFF(PCIATAState, IBase);
+ GEN_CHECK_OFF(PCIATAState, ILeds);
+ GEN_CHECK_OFF(PCIATAState, pLedsConnector);
+ GEN_CHECK_OFF(PCIATAState, fRCEnabled);
+ GEN_CHECK_OFF(PCIATAState, fR0Enabled);
+
+#ifdef VBOX_WITH_USB
+ /* USB/DevOHCI.cpp */
+ GEN_CHECK_SIZE(OHCIHUBPORT);
+ GEN_CHECK_OFF(OHCIHUBPORT, fReg);
+ GEN_CHECK_OFF(OHCIHUBPORT, pDev);
+
+ GEN_CHECK_SIZE(OHCIROOTHUB);
+ GEN_CHECK_OFF(OHCIROOTHUB, pIBase);
+ GEN_CHECK_OFF(OHCIROOTHUB, pIRhConn);
+ GEN_CHECK_OFF(OHCIROOTHUB, pIDev);
+ GEN_CHECK_OFF(OHCIROOTHUB, IBase);
+ GEN_CHECK_OFF(OHCIROOTHUB, IRhPort);
+ GEN_CHECK_OFF(OHCIROOTHUB, status);
+ GEN_CHECK_OFF(OHCIROOTHUB, desc_a);
+ GEN_CHECK_OFF(OHCIROOTHUB, desc_b);
+ GEN_CHECK_OFF(OHCIROOTHUB, aPorts);
+ GEN_CHECK_OFF(OHCIROOTHUB, aPorts[1]);
+ GEN_CHECK_OFF(OHCIROOTHUB, aPorts[OHCI_NDP_MAX - 1]);
+ GEN_CHECK_OFF(OHCIROOTHUB, pOhci);
+
+ GEN_CHECK_SIZE(OHCI);
+ GEN_CHECK_OFF(OHCI, PciDev);
+ GEN_CHECK_OFF(OHCI, MMIOBase);
+ GEN_CHECK_OFF(OHCI, pEndOfFrameTimerR3);
+ GEN_CHECK_OFF(OHCI, pEndOfFrameTimerR0);
+ GEN_CHECK_OFF(OHCI, pEndOfFrameTimerRC);
+ GEN_CHECK_OFF(OHCI, pDevInsR3);
+ GEN_CHECK_OFF(OHCI, pDevInsR0);
+ GEN_CHECK_OFF(OHCI, pDevInsRC);
+ GEN_CHECK_OFF(OHCI, SofTime);
+ //GEN_CHECK_OFF(OHCI, dqic:3);
+ //GEN_CHECK_OFF(OHCI, fno:1);
+ GEN_CHECK_OFF(OHCI, RootHub);
+ GEN_CHECK_OFF(OHCI, ctl);
+ GEN_CHECK_OFF(OHCI, status);
+ GEN_CHECK_OFF(OHCI, intr_status);
+ GEN_CHECK_OFF(OHCI, intr);
+ GEN_CHECK_OFF(OHCI, hcca);
+ GEN_CHECK_OFF(OHCI, per_cur);
+ GEN_CHECK_OFF(OHCI, ctrl_cur);
+ GEN_CHECK_OFF(OHCI, ctrl_head);
+ GEN_CHECK_OFF(OHCI, bulk_cur);
+ GEN_CHECK_OFF(OHCI, bulk_head);
+ GEN_CHECK_OFF(OHCI, done);
+ //GEN_CHECK_OFF(OHCI, fsmps:15);
+ //GEN_CHECK_OFF(OHCI, fit:1);
+ //GEN_CHECK_OFF(OHCI, fi:14);
+ //GEN_CHECK_OFF(OHCI, frt:1);
+ GEN_CHECK_OFF(OHCI, HcFmNumber);
+ GEN_CHECK_OFF(OHCI, pstart);
+ GEN_CHECK_OFF(OHCI, cTicksPerFrame);
+ GEN_CHECK_OFF(OHCI, cTicksPerUsbTick);
+ GEN_CHECK_OFF(OHCI, cInFlight);
+ GEN_CHECK_OFF(OHCI, aInFlight);
+ GEN_CHECK_OFF(OHCI, aInFlight[0].GCPhysTD);
+ GEN_CHECK_OFF(OHCI, aInFlight[0].pUrb);
+ GEN_CHECK_OFF(OHCI, aInFlight[1]);
+ GEN_CHECK_OFF(OHCI, cInDoneQueue);
+ GEN_CHECK_OFF(OHCI, aInDoneQueue);
+ GEN_CHECK_OFF(OHCI, aInDoneQueue[0].GCPhysTD);
+ GEN_CHECK_OFF(OHCI, aInDoneQueue[1]);
+ GEN_CHECK_OFF(OHCI, u32FmDoneQueueTail);
+ GEN_CHECK_OFF(OHCI, pLoad);
+# ifdef VBOX_WITH_STATISTICS
+ GEN_CHECK_OFF(OHCI, StatCanceledIsocUrbs);
+ GEN_CHECK_OFF(OHCI, StatCanceledGenUrbs);
+ GEN_CHECK_OFF(OHCI, StatDroppedUrbs);
+ GEN_CHECK_OFF(OHCI, StatTimer);
+# endif
+ GEN_CHECK_OFF(OHCI, CsIrq);
+ GEN_CHECK_OFF(OHCI, CritSect);
+
+# ifdef VBOX_WITH_EHCI_IMPL
+ /* USB/DevEHCI.cpp */
+ GEN_CHECK_SIZE(EHCIHUBPORT);
+ GEN_CHECK_OFF(EHCIHUBPORT, fReg);
+ GEN_CHECK_OFF(EHCIHUBPORT, pDev);
+
+ GEN_CHECK_SIZE(EHCIROOTHUB);
+ GEN_CHECK_OFF(EHCIROOTHUB, pIBase);
+ GEN_CHECK_OFF(EHCIROOTHUB, pIRhConn);
+ GEN_CHECK_OFF(EHCIROOTHUB, pIDev);
+ GEN_CHECK_OFF(EHCIROOTHUB, IBase);
+ GEN_CHECK_OFF(EHCIROOTHUB, IRhPort);
+ GEN_CHECK_OFF(EHCIROOTHUB, Led);
+ GEN_CHECK_OFF(EHCIROOTHUB, ILeds);
+ GEN_CHECK_OFF(EHCIROOTHUB, pLedsConnector);
+ GEN_CHECK_OFF(EHCIROOTHUB, aPorts);
+ GEN_CHECK_OFF(EHCIROOTHUB, aPorts[1]);
+ GEN_CHECK_OFF(EHCIROOTHUB, aPorts[EHCI_NDP_MAX - 1]);
+ GEN_CHECK_OFF(EHCIROOTHUB, pEhci);
+
+ GEN_CHECK_SIZE(EHCI);
+ GEN_CHECK_OFF(EHCI, PciDev);
+ GEN_CHECK_OFF(EHCI, MMIOBase);
+ GEN_CHECK_OFF(EHCI, pDevInsR3);
+ GEN_CHECK_OFF(EHCI, pDevInsR0);
+ GEN_CHECK_OFF(EHCI, pDevInsRC);
+ GEN_CHECK_OFF(EHCI, MMIOBase);
+ GEN_CHECK_OFF(EHCI, SofTime);
+ GEN_CHECK_OFF(EHCI, RootHub);
+ GEN_CHECK_OFF(EHCI, cap_length);
+ GEN_CHECK_OFF(EHCI, hci_version);
+ GEN_CHECK_OFF(EHCI, hcs_params);
+ GEN_CHECK_OFF(EHCI, hcc_params);
+ GEN_CHECK_OFF(EHCI, cmd);
+ GEN_CHECK_OFF(EHCI, intr_status);
+ GEN_CHECK_OFF(EHCI, intr);
+ GEN_CHECK_OFF(EHCI, frame_idx);
+ GEN_CHECK_OFF(EHCI, ds_segment);
+ GEN_CHECK_OFF(EHCI, periodic_list_base);
+ GEN_CHECK_OFF(EHCI, async_list_base);
+ GEN_CHECK_OFF(EHCI, config);
+ GEN_CHECK_OFF(EHCI, uIrqInterval);
+ GEN_CHECK_OFF(EHCI, HcFmNumber);
+ GEN_CHECK_OFF(EHCI, uFramesPerTimerCall);
+ GEN_CHECK_OFF(EHCI, cTicksPerFrame);
+ GEN_CHECK_OFF(EHCI, cTicksPerUsbTick);
+ GEN_CHECK_OFF(EHCI, cInFlight);
+ GEN_CHECK_OFF(EHCI, aInFlight);
+ GEN_CHECK_OFF(EHCI, aInFlight[0].GCPhysTD);
+ GEN_CHECK_OFF(EHCI, aInFlight[0].pUrb);
+ GEN_CHECK_OFF(EHCI, aInFlight[1]);
+ GEN_CHECK_OFF(EHCI, aInFlight[256]);
+ GEN_CHECK_OFF(EHCI, pLoad);
+ GEN_CHECK_OFF(EHCI, fAsyncTraversalTimerActive);
+# ifdef VBOX_WITH_STATISTICS
+ GEN_CHECK_OFF(EHCI, StatCanceledIsocUrbs);
+ GEN_CHECK_OFF(EHCI, StatCanceledGenUrbs);
+ GEN_CHECK_OFF(EHCI, StatDroppedUrbs);
+# endif
+ GEN_CHECK_OFF(EHCI, u64TimerHz);
+ GEN_CHECK_OFF(EHCI, cIdleCycles);
+ GEN_CHECK_OFF(EHCI, uFrameRate);
+ GEN_CHECK_OFF(EHCI, fIdle);
+ GEN_CHECK_OFF(EHCI, hThreadFrame);
+ GEN_CHECK_OFF(EHCI, hSemEventFrame);
+ GEN_CHECK_OFF(EHCI, fBusStarted);
+ GEN_CHECK_OFF(EHCI, CsIrq);
+ GEN_CHECK_OFF(EHCI, uFrameRateDefault);
+ GEN_CHECK_OFF(EHCI, nsWait);
+ GEN_CHECK_OFF(EHCI, CritSect);
+# endif /* VBOX_WITH_EHCI_IMPL */
+
+# ifdef VBOX_WITH_XHCI_IMPL
+ /* USB/DevXHCI.cpp */
+ GEN_CHECK_SIZE(XHCIHUBPORT);
+ GEN_CHECK_OFF(XHCIHUBPORT, portsc);
+ GEN_CHECK_OFF(XHCIHUBPORT, portpm);
+ GEN_CHECK_OFF(XHCIHUBPORT, portli);
+ GEN_CHECK_OFF(XHCIHUBPORT, pDev);
+
+ GEN_CHECK_SIZE(XHCIROOTHUB);
+ GEN_CHECK_OFF(XHCIROOTHUB, pIBase);
+ GEN_CHECK_OFF(XHCIROOTHUB, pIRhConn);
+ GEN_CHECK_OFF(XHCIROOTHUB, pIDev);
+ GEN_CHECK_OFF(XHCIROOTHUB, IBase);
+ GEN_CHECK_OFF(XHCIROOTHUB, IRhPort);
+ GEN_CHECK_OFF(XHCIROOTHUB, Led);
+ GEN_CHECK_OFF(XHCIROOTHUB, cPortsImpl);
+ GEN_CHECK_OFF(XHCIROOTHUB, pXhci);
+
+ GEN_CHECK_SIZE(XHCIINTRPTR);
+ GEN_CHECK_OFF(XHCIINTRPTR, iman);
+ GEN_CHECK_OFF(XHCIINTRPTR, imod);
+ GEN_CHECK_OFF(XHCIINTRPTR, erstba);
+ GEN_CHECK_OFF(XHCIINTRPTR, erdp);
+ GEN_CHECK_OFF(XHCIINTRPTR, erep);
+ GEN_CHECK_OFF(XHCIINTRPTR, erst_idx);
+ GEN_CHECK_OFF(XHCIINTRPTR, trb_count);
+ GEN_CHECK_OFF(XHCIINTRPTR, evtr_pcs);
+ GEN_CHECK_OFF(XHCIINTRPTR, ipe);
+
+ GEN_CHECK_SIZE(XHCI);
+ GEN_CHECK_OFF(XHCI, PciDev);
+ GEN_CHECK_OFF(XHCI, pDevInsR3);
+ GEN_CHECK_OFF(XHCI, pDevInsR0);
+ GEN_CHECK_OFF(XHCI, pDevInsRC);
+ GEN_CHECK_OFF(XHCI, pNotifierQueueR3);
+ GEN_CHECK_OFF(XHCI, pNotifierQueueR0);
+ GEN_CHECK_OFF(XHCI, pNotifierQueueRC);
+ GEN_CHECK_OFF(XHCI, pWrapTimerR3);
+ GEN_CHECK_OFF(XHCI, pWrapTimerR0);
+ GEN_CHECK_OFF(XHCI, pWrapTimerRC);
+ GEN_CHECK_OFF(XHCI, pWorkerThread);
+ GEN_CHECK_OFF(XHCI, pSupDrvSession);
+ GEN_CHECK_OFF(XHCI, hEvtProcess);
+ GEN_CHECK_OFF(XHCI, fWrkThreadSleeping);
+ GEN_CHECK_OFF(XHCI, u32TasksNew);
+ GEN_CHECK_OFF(XHCI, ILeds);
+ GEN_CHECK_OFF(XHCI, pLedsConnector);
+ GEN_CHECK_OFF(XHCI, MMIOBase);
+ GEN_CHECK_OFF(XHCI, RootHub2);
+ GEN_CHECK_OFF(XHCI, RootHub3);
+ GEN_CHECK_OFF(XHCI, aPorts);
+ GEN_CHECK_OFF(XHCI, aPorts[1]);
+ GEN_CHECK_OFF(XHCI, aPorts[XHCI_NDP_MAX - 1]);
+ GEN_CHECK_OFF(XHCI, cap_length);
+ GEN_CHECK_OFF(XHCI, hci_version);
+ GEN_CHECK_OFF(XHCI, hcs_params3);
+ GEN_CHECK_OFF(XHCI, hcc_params);
+ GEN_CHECK_OFF(XHCI, dbell_off);
+ GEN_CHECK_OFF(XHCI, rts_off);
+ GEN_CHECK_OFF(XHCI, cmd);
+ GEN_CHECK_OFF(XHCI, status);
+ GEN_CHECK_OFF(XHCI, dnctrl);
+ GEN_CHECK_OFF(XHCI, config);
+ GEN_CHECK_OFF(XHCI, crcr);
+ GEN_CHECK_OFF(XHCI, dcbaap);
+ GEN_CHECK_OFF(XHCI, abExtCap);
+ GEN_CHECK_OFF(XHCI, cbExtCap);
+ GEN_CHECK_OFF(XHCI, cmdr_dqp);
+ GEN_CHECK_OFF(XHCI, cmdr_ccs);
+ GEN_CHECK_OFF(XHCI, aSlotState);
+ GEN_CHECK_OFF(XHCI, aBellsRung);
+ GEN_CHECK_OFF(XHCI, pLoad);
+# ifdef VBOX_WITH_STATISTICS
+ GEN_CHECK_OFF(XHCI, StatErrorIsocUrbs);
+ GEN_CHECK_OFF(XHCI, StatErrorIsocPkts);
+ GEN_CHECK_OFF(XHCI, StatEventsWritten);
+ GEN_CHECK_OFF(XHCI, StatEventsDropped);
+ GEN_CHECK_OFF(XHCI, StatIntrsPending);
+ GEN_CHECK_OFF(XHCI, StatIntrsSet);
+ GEN_CHECK_OFF(XHCI, StatIntrsNotSet);
+ GEN_CHECK_OFF(XHCI, StatIntrsCleared);
+# endif
+# endif /* VBOX_WITH_XHCI_IMPL */
+#endif /* VBOX_WITH_USB */
+
+ /* Parallel/DevParallel.cpp */
+ GEN_CHECK_SIZE(PARALLELPORT);
+ GEN_CHECK_OFF(PARALLELPORT, pDevInsR3);
+ GEN_CHECK_OFF(PARALLELPORT, pDevInsR0);
+ GEN_CHECK_OFF(PARALLELPORT, pDevInsRC);
+ GEN_CHECK_OFF(PARALLELPORT, IBase);
+ GEN_CHECK_OFF(PARALLELPORT, IHostParallelPort);
+ GEN_CHECK_OFF(PARALLELPORT, pDrvHostParallelConnector);
+ GEN_CHECK_OFF(PARALLELPORT, fGCEnabled);
+ GEN_CHECK_OFF(PARALLELPORT, fR0Enabled);
+ GEN_CHECK_OFF(PARALLELPORT, fEppTimeout);
+ GEN_CHECK_OFF(PARALLELPORT, IOBase);
+ GEN_CHECK_OFF(PARALLELPORT, iIrq);
+ GEN_CHECK_OFF(PARALLELPORT, regData);
+ GEN_CHECK_OFF(PARALLELPORT, regStatus);
+ GEN_CHECK_OFF(PARALLELPORT, regControl);
+ GEN_CHECK_OFF(PARALLELPORT, regEppAddr);
+ GEN_CHECK_OFF(PARALLELPORT, regEppData);
+#if 0
+ GEN_CHECK_OFF(PARALLELPORT, reg_ecp_ecr);
+ GEN_CHECK_OFF(PARALLELPORT, reg_ecp_base_plus_400h);
+ GEN_CHECK_OFF(PARALLELPORT, reg_ecp_config_b);
+ GEN_CHECK_OFF(PARALLELPORT, ecp_fifo);
+ GEN_CHECK_OFF(PARALLELPORT, ecp_fifo[1]);
+ GEN_CHECK_OFF(PARALLELPORT, act_fifo_pos_write);
+ GEN_CHECK_OFF(PARALLELPORT, act_fifo_pos_read);
+#endif
+
+ /* Serial/UartCore.cpp */
+ GEN_CHECK_SIZE(UARTCORE);
+ GEN_CHECK_OFF(UARTCORE, CritSect);
+ GEN_CHECK_OFF(UARTCORE, pDevInsR3);
+ GEN_CHECK_OFF(UARTCORE, pDevInsR0);
+ GEN_CHECK_OFF(UARTCORE, pDevInsRC);
+ GEN_CHECK_OFF(UARTCORE, iLUN);
+ GEN_CHECK_OFF(UARTCORE, IBase);
+ GEN_CHECK_OFF(UARTCORE, ISerialPort);
+ GEN_CHECK_OFF(UARTCORE, pDrvBase);
+ GEN_CHECK_OFF(UARTCORE, pDrvSerial);
+ GEN_CHECK_OFF(UARTCORE, fFlags);
+ GEN_CHECK_OFF(UARTCORE, enmType);
+ GEN_CHECK_OFF(UARTCORE, pTimerRcvFifoTimeoutR3);
+ GEN_CHECK_OFF(UARTCORE, pTimerTxUnconnectedR3);
+ GEN_CHECK_OFF(UARTCORE, pfnUartIrqReqR3);
+ GEN_CHECK_OFF(UARTCORE, pTimerRcvFifoTimeoutR0);
+ GEN_CHECK_OFF(UARTCORE, pTimerTxUnconnectedR0);
+ GEN_CHECK_OFF(UARTCORE, pfnUartIrqReqR0);
+ GEN_CHECK_OFF(UARTCORE, pTimerRcvFifoTimeoutRC);
+ GEN_CHECK_OFF(UARTCORE, pTimerTxUnconnectedRC);
+ GEN_CHECK_OFF(UARTCORE, pfnUartIrqReqRC);
+ GEN_CHECK_OFF(UARTCORE, uRegDivisor);
+ GEN_CHECK_OFF(UARTCORE, uRegRbr);
+ GEN_CHECK_OFF(UARTCORE, uRegThr);
+ GEN_CHECK_OFF(UARTCORE, uRegIer);
+ GEN_CHECK_OFF(UARTCORE, uRegIir);
+ GEN_CHECK_OFF(UARTCORE, uRegFcr);
+ GEN_CHECK_OFF(UARTCORE, uRegLcr);
+ GEN_CHECK_OFF(UARTCORE, uRegMcr);
+ GEN_CHECK_OFF(UARTCORE, uRegLsr);
+ GEN_CHECK_OFF(UARTCORE, uRegMsr);
+ GEN_CHECK_OFF(UARTCORE, uRegScr);
+ GEN_CHECK_OFF(UARTCORE, fIrqCtiPending);
+ GEN_CHECK_OFF(UARTCORE, fThreEmptyPending);
+ GEN_CHECK_OFF(UARTCORE, FifoXmit);
+ GEN_CHECK_OFF(UARTCORE, FifoRecv);
+ GEN_CHECK_OFF(UARTCORE, cSymbolXferTicks);
+ GEN_CHECK_OFF(UARTCORE, cbAvailRdr);
+
+ /* Serial/DevSerial.cpp */
+ GEN_CHECK_SIZE(DEVSERIAL);
+ GEN_CHECK_OFF(DEVSERIAL, pDevInsR3);
+ GEN_CHECK_OFF(DEVSERIAL, pDevInsR0);
+ GEN_CHECK_OFF(DEVSERIAL, pDevInsRC);
+ GEN_CHECK_OFF(DEVSERIAL, fR0Enabled);
+ GEN_CHECK_OFF(DEVSERIAL, fRCEnabled);
+ GEN_CHECK_OFF(DEVSERIAL, uIrq);
+ GEN_CHECK_OFF(DEVSERIAL, PortBase);
+ GEN_CHECK_OFF(DEVSERIAL, UartCore);
+
+ /* Serial/DevOxPcie958.cpp */
+ GEN_CHECK_SIZE(DEVOX958);
+ GEN_CHECK_OFF(DEVOX958, PciDev);
+ GEN_CHECK_OFF(DEVOX958, pDevInsR3);
+ GEN_CHECK_OFF(DEVOX958, pDevInsR0);
+ GEN_CHECK_OFF(DEVOX958, pDevInsRC);
+ GEN_CHECK_OFF(DEVOX958, fR0Enabled);
+ GEN_CHECK_OFF(DEVOX958, fRCEnabled);
+ GEN_CHECK_OFF(DEVOX958, u32RegIrqStsGlob);
+ GEN_CHECK_OFF(DEVOX958, u32RegIrqEnGlob);
+ GEN_CHECK_OFF(DEVOX958, u32RegIrqEnWake);
+ GEN_CHECK_OFF(DEVOX958, cUarts);
+ GEN_CHECK_OFF(DEVOX958, GCPhysMMIO);
+ GEN_CHECK_OFF(DEVOX958, aUarts);
+ GEN_CHECK_OFF(DEVOX958, aUarts[OX958_UARTS_MAX - 1]);
+
+#ifdef VBOX_WITH_AHCI
+ /* Storage/DevAHCI.cpp */
+
+ GEN_CHECK_SIZE(AHCIPort);
+ GEN_CHECK_OFF(AHCIPort, pDevInsR3);
+ GEN_CHECK_OFF(AHCIPort, pDevInsR0);
+ GEN_CHECK_OFF(AHCIPort, pDevInsRC);
+ GEN_CHECK_OFF(AHCIPort, pAhciR3);
+ GEN_CHECK_OFF(AHCIPort, pAhciR0);
+ GEN_CHECK_OFF(AHCIPort, pAhciRC);
+ GEN_CHECK_OFF(AHCIPort, regCLB);
+ GEN_CHECK_OFF(AHCIPort, regCLBU);
+ GEN_CHECK_OFF(AHCIPort, regFB);
+ GEN_CHECK_OFF(AHCIPort, regFBU);
+ GEN_CHECK_OFF(AHCIPort, regIS);
+ GEN_CHECK_OFF(AHCIPort, regIE);
+ GEN_CHECK_OFF(AHCIPort, regCMD);
+ GEN_CHECK_OFF(AHCIPort, regTFD);
+ GEN_CHECK_OFF(AHCIPort, regSIG);
+ GEN_CHECK_OFF(AHCIPort, regSSTS);
+ GEN_CHECK_OFF(AHCIPort, regSCTL);
+ GEN_CHECK_OFF(AHCIPort, regSERR);
+ GEN_CHECK_OFF(AHCIPort, regSACT);
+ GEN_CHECK_OFF(AHCIPort, regCI);
+ GEN_CHECK_OFF(AHCIPort, cTasksActive);
+ GEN_CHECK_OFF(AHCIPort, GCPhysAddrClb);
+ GEN_CHECK_OFF(AHCIPort, GCPhysAddrFb);
+ GEN_CHECK_OFF(AHCIPort, fPoweredOn);
+ GEN_CHECK_OFF(AHCIPort, fSpunUp);
+ GEN_CHECK_OFF(AHCIPort, fFirstD2HFisSent);
+ GEN_CHECK_OFF(AHCIPort, fATAPI);
+ GEN_CHECK_OFF(AHCIPort, fPortReset);
+ GEN_CHECK_OFF(AHCIPort, fTrimEnabled);
+ GEN_CHECK_OFF(AHCIPort, fResetDevice);
+ GEN_CHECK_OFF(AHCIPort, fHotpluggable);
+ GEN_CHECK_OFF(AHCIPort, fRedo);
+ GEN_CHECK_OFF(AHCIPort, fWrkThreadSleeping);
+ GEN_CHECK_OFF(AHCIPort, cTotalSectors);
+ GEN_CHECK_OFF(AHCIPort, cbSector);
+ GEN_CHECK_OFF(AHCIPort, cMultSectors);
+ GEN_CHECK_OFF(AHCIPort, uATATransferMode);
+ GEN_CHECK_OFF(AHCIPort, abATAPISense);
+ GEN_CHECK_OFF(AHCIPort, cLogSectorsPerPhysicalExp);
+ GEN_CHECK_OFF(AHCIPort, iLUN);
+ GEN_CHECK_OFF(AHCIPort, u32TasksFinished);
+ GEN_CHECK_OFF(AHCIPort, u32QueuedTasksFinished);
+ GEN_CHECK_OFF(AHCIPort, u32TasksNew);
+ GEN_CHECK_OFF(AHCIPort, u32TasksRedo);
+ GEN_CHECK_OFF(AHCIPort, u32CurrentCommandSlot);
+ GEN_CHECK_OFF(AHCIPort, pDrvBase);
+ GEN_CHECK_OFF(AHCIPort, pDrvMedia);
+ GEN_CHECK_OFF(AHCIPort, pDrvMediaEx);
+ GEN_CHECK_OFF(AHCIPort, pszDesc);
+ GEN_CHECK_OFF(AHCIPort, IBase);
+ GEN_CHECK_OFF(AHCIPort, IPort);
+ GEN_CHECK_OFF(AHCIPort, IMediaExPort);
+ GEN_CHECK_OFF(AHCIPort, PCHSGeometry);
+ GEN_CHECK_OFF(AHCIPort, Led);
+ GEN_CHECK_OFF(AHCIPort, pAsyncIOThread);
+
+ GEN_CHECK_OFF(AHCIPort, pTaskErr);
+ GEN_CHECK_OFF(AHCIPort, hEvtProcess);
+ GEN_CHECK_OFF(AHCIPort, szSerialNumber);
+ GEN_CHECK_OFF(AHCIPort, szSerialNumber[AHCI_SERIAL_NUMBER_LENGTH]); /* One additional byte for the termination.*/
+ GEN_CHECK_OFF(AHCIPort, szFirmwareRevision);
+ GEN_CHECK_OFF(AHCIPort, szFirmwareRevision[AHCI_FIRMWARE_REVISION_LENGTH]); /* One additional byte for the termination.*/
+ GEN_CHECK_OFF(AHCIPort, szModelNumber);
+ GEN_CHECK_OFF(AHCIPort, szModelNumber[AHCI_MODEL_NUMBER_LENGTH]); /* One additional byte for the termination.*/
+ GEN_CHECK_OFF(AHCIPort, szInquiryVendorId);
+ GEN_CHECK_OFF(AHCIPort, szInquiryVendorId[AHCI_ATAPI_INQUIRY_VENDOR_ID_LENGTH]); /* One additional byte for the termination.*/
+ GEN_CHECK_OFF(AHCIPort, szInquiryProductId);
+ GEN_CHECK_OFF(AHCIPort, szInquiryProductId[AHCI_ATAPI_INQUIRY_PRODUCT_ID_LENGTH]); /* One additional byte for the termination.*/
+ GEN_CHECK_OFF(AHCIPort, szInquiryRevision);
+ GEN_CHECK_OFF(AHCIPort, szInquiryRevision[AHCI_ATAPI_INQUIRY_REVISION_LENGTH]); /* One additional byte for the termination.*/
+ GEN_CHECK_OFF(AHCIPort, cErrors);
+ GEN_CHECK_OFF(AHCIPort, fRedo);
+
+ GEN_CHECK_SIZE(AHCI);
+ GEN_CHECK_OFF(AHCI, dev);
+ GEN_CHECK_OFF(AHCI, pDevInsR3);
+ GEN_CHECK_OFF(AHCI, pDevInsR0);
+ GEN_CHECK_OFF(AHCI, pDevInsRC);
+ GEN_CHECK_OFF(AHCI, IBase);
+ GEN_CHECK_OFF(AHCI, ILeds);
+ GEN_CHECK_OFF(AHCI, pLedsConnector);
+ GEN_CHECK_OFF(AHCI, MMIOBase);
+ GEN_CHECK_OFF(AHCI, regHbaCap);
+ GEN_CHECK_OFF(AHCI, regHbaCtrl);
+ GEN_CHECK_OFF(AHCI, regHbaIs);
+ GEN_CHECK_OFF(AHCI, regHbaPi);
+ GEN_CHECK_OFF(AHCI, regHbaVs);
+ GEN_CHECK_OFF(AHCI, regHbaCccCtl);
+ GEN_CHECK_OFF(AHCI, regHbaCccPorts);
+ GEN_CHECK_OFF(AHCI, regIdx);
+ GEN_CHECK_OFF(AHCI, pHbaCccTimerR3);
+ GEN_CHECK_OFF(AHCI, pHbaCccTimerR0);
+ GEN_CHECK_OFF(AHCI, pHbaCccTimerRC);
+ GEN_CHECK_OFF(AHCI, pNotifierQueueR3);
+ GEN_CHECK_OFF(AHCI, pNotifierQueueR0);
+ GEN_CHECK_OFF(AHCI, pNotifierQueueRC);
+ GEN_CHECK_OFF(AHCI, uCccPortNr);
+ GEN_CHECK_OFF(AHCI, uCccTimeout);
+ GEN_CHECK_OFF(AHCI, uCccNr);
+ GEN_CHECK_OFF(AHCI, uCccCurrentNr);
+ GEN_CHECK_OFF(AHCI, ahciPort);
+ GEN_CHECK_OFF(AHCI, ahciPort[AHCI_MAX_NR_PORTS_IMPL-1]);
+ GEN_CHECK_OFF(AHCI, lock);
+ GEN_CHECK_OFF(AHCI, u32PortsInterrupted);
+ GEN_CHECK_OFF(AHCI, cThreadsActive);
+ GEN_CHECK_OFF(AHCI, fReset);
+ GEN_CHECK_OFF(AHCI, f64BitAddr);
+ GEN_CHECK_OFF(AHCI, fGCEnabled);
+ GEN_CHECK_OFF(AHCI, fR0Enabled);
+ GEN_CHECK_OFF(AHCI, fSignalIdle);
+ GEN_CHECK_OFF(AHCI, fBootable);
+ GEN_CHECK_OFF(AHCI, fLegacyPortResetMethod);
+ GEN_CHECK_OFF(AHCI, cPortsImpl);
+ GEN_CHECK_OFF(AHCI, cCmdSlotsAvail);
+ GEN_CHECK_OFF(AHCI, f8ByteMMIO4BytesWrittenSuccessfully);
+ GEN_CHECK_OFF(AHCI, pSupDrvSession);
+#endif /* VBOX_WITH_AHCI */
+
+#ifdef VBOX_WITH_E1000
+ GEN_CHECK_SIZE(EEPROM93C46);
+ GEN_CHECK_OFF(EEPROM93C46, m_eState);
+ GEN_CHECK_OFF(EEPROM93C46, m_au16Data);
+ GEN_CHECK_OFF(EEPROM93C46, m_fWriteEnabled);
+ GEN_CHECK_OFF(EEPROM93C46, m_u16Word);
+ GEN_CHECK_OFF(EEPROM93C46, m_u16Mask);
+ GEN_CHECK_OFF(EEPROM93C46, m_u16Addr);
+ GEN_CHECK_OFF(EEPROM93C46, m_u32InternalWires);
+ GEN_CHECK_OFF(EEPROM93C46, m_eOp);
+
+ GEN_CHECK_SIZE(E1KSTATE);
+ GEN_CHECK_OFF(E1KSTATE, IBase);
+ GEN_CHECK_OFF(E1KSTATE, INetworkDown);
+ GEN_CHECK_OFF(E1KSTATE, INetworkConfig);
+ GEN_CHECK_OFF(E1KSTATE, ILeds);
+ GEN_CHECK_OFF(E1KSTATE, pDrvBase);
+ GEN_CHECK_OFF(E1KSTATE, pDrvR3);
+ GEN_CHECK_OFF(E1KSTATE, pDrvR0);
+ GEN_CHECK_OFF(E1KSTATE, pDrvRC);
+ GEN_CHECK_OFF(E1KSTATE, pLedsConnector);
+ GEN_CHECK_OFF(E1KSTATE, pDevInsR3);
+ GEN_CHECK_OFF(E1KSTATE, pDevInsR0);
+ GEN_CHECK_OFF(E1KSTATE, pDevInsRC);
+ GEN_CHECK_OFF(E1KSTATE, pTxQueueR3);
+ GEN_CHECK_OFF(E1KSTATE, pTxQueueR0);
+ GEN_CHECK_OFF(E1KSTATE, pTxQueueRC);
+ GEN_CHECK_OFF(E1KSTATE, pCanRxQueueR3);
+ GEN_CHECK_OFF(E1KSTATE, pCanRxQueueR0);
+ GEN_CHECK_OFF(E1KSTATE, pCanRxQueueRC);
+ GEN_CHECK_OFF(E1KSTATE, pRIDTimerR3);
+ GEN_CHECK_OFF(E1KSTATE, pRIDTimerR0);
+ GEN_CHECK_OFF(E1KSTATE, pRIDTimerRC);
+ GEN_CHECK_OFF(E1KSTATE, pRADTimerR3);
+ GEN_CHECK_OFF(E1KSTATE, pRADTimerR0);
+ GEN_CHECK_OFF(E1KSTATE, pRADTimerRC);
+ GEN_CHECK_OFF(E1KSTATE, pTIDTimerR3);
+ GEN_CHECK_OFF(E1KSTATE, pTIDTimerR0);
+ GEN_CHECK_OFF(E1KSTATE, pTIDTimerRC);
+ GEN_CHECK_OFF(E1KSTATE, pTADTimerR3);
+ GEN_CHECK_OFF(E1KSTATE, pTADTimerR0);
+ GEN_CHECK_OFF(E1KSTATE, pTADTimerRC);
+ GEN_CHECK_OFF(E1KSTATE, pIntTimerR3);
+ GEN_CHECK_OFF(E1KSTATE, pIntTimerR0);
+ GEN_CHECK_OFF(E1KSTATE, pIntTimerRC);
+ GEN_CHECK_OFF(E1KSTATE, pLUTimerR3);
+ GEN_CHECK_OFF(E1KSTATE, pLUTimerR0);
+ GEN_CHECK_OFF(E1KSTATE, pLUTimerRC);
+ GEN_CHECK_OFF(E1KSTATE, cs);
+# ifndef E1K_GLOBAL_MUTEX
+ GEN_CHECK_OFF(E1KSTATE, csRx);
+# endif
+ GEN_CHECK_OFF(E1KSTATE, addrMMReg);
+ GEN_CHECK_OFF(E1KSTATE, macConfigured);
+ GEN_CHECK_OFF(E1KSTATE, IOPortBase);
+ GEN_CHECK_OFF(E1KSTATE, pciDevice);
+ GEN_CHECK_OFF(E1KSTATE, u64AckedAt);
+ GEN_CHECK_OFF(E1KSTATE, fIntRaised);
+ GEN_CHECK_OFF(E1KSTATE, fCableConnected);
+ GEN_CHECK_OFF(E1KSTATE, fR0Enabled);
+ GEN_CHECK_OFF(E1KSTATE, fRCEnabled);
+ GEN_CHECK_OFF(E1KSTATE, auRegs[E1K_NUM_OF_32BIT_REGS]);
+ GEN_CHECK_OFF(E1KSTATE, led);
+ GEN_CHECK_OFF(E1KSTATE, u32PktNo);
+ GEN_CHECK_OFF(E1KSTATE, uSelectedReg);
+ GEN_CHECK_OFF(E1KSTATE, auMTA[128]);
+ GEN_CHECK_OFF(E1KSTATE, aRecAddr);
+ GEN_CHECK_OFF(E1KSTATE, auVFTA[128]);
+ GEN_CHECK_OFF(E1KSTATE, u16RxBSize);
+ GEN_CHECK_OFF(E1KSTATE, fLocked);
+ GEN_CHECK_OFF(E1KSTATE, fDelayInts);
+ GEN_CHECK_OFF(E1KSTATE, fIntMaskUsed);
+ GEN_CHECK_OFF(E1KSTATE, fMaybeOutOfSpace);
+ GEN_CHECK_OFF(E1KSTATE, hEventMoreRxDescAvail);
+ GEN_CHECK_OFF(E1KSTATE, contextTSE);
+ GEN_CHECK_OFF(E1KSTATE, contextNormal);
+# ifdef E1K_WITH_TXD_CACHE
+ GEN_CHECK_OFF(E1KSTATE, aTxDescriptors);
+ GEN_CHECK_OFF(E1KSTATE, nTxDFetched);
+ GEN_CHECK_OFF(E1KSTATE, iTxDCurrent);
+ GEN_CHECK_OFF(E1KSTATE, fGSO);
+ GEN_CHECK_OFF(E1KSTATE, cbTxAlloc);
+# endif
+ GEN_CHECK_OFF(E1KSTATE, GsoCtx);
+ GEN_CHECK_OFF(E1KSTATE, uTxFallback);
+ GEN_CHECK_OFF(E1KSTATE, fVTag);
+ GEN_CHECK_OFF(E1KSTATE, u16VTagTCI);
+ GEN_CHECK_OFF(E1KSTATE, aTxPacketFallback[E1K_MAX_TX_PKT_SIZE]);
+ GEN_CHECK_OFF(E1KSTATE, u16TxPktLen);
+ GEN_CHECK_OFF(E1KSTATE, fIPcsum);
+ GEN_CHECK_OFF(E1KSTATE, fTCPcsum);
+ GEN_CHECK_OFF(E1KSTATE, u32PayRemain);
+ GEN_CHECK_OFF(E1KSTATE, u16HdrRemain);
+ GEN_CHECK_OFF(E1KSTATE, u16SavedFlags);
+ GEN_CHECK_OFF(E1KSTATE, u32SavedCsum);
+ GEN_CHECK_OFF(E1KSTATE, eeprom);
+ GEN_CHECK_OFF(E1KSTATE, phy);
+ GEN_CHECK_OFF(E1KSTATE, StatReceiveBytes);
+#endif /* VBOX_WITH_E1000 */
+
+ /* VMMDev*.cpp/h */
+ GEN_CHECK_SIZE(VMMDEV);
+ GEN_CHECK_OFF(VMMDEV, PciDev);
+ GEN_CHECK_OFF(VMMDEV, CritSect);
+ GEN_CHECK_OFF(VMMDEV, hypervisorSize);
+ GEN_CHECK_OFF(VMMDEV, mouseCapabilities);
+ GEN_CHECK_OFF(VMMDEV, mouseXAbs);
+ GEN_CHECK_OFF(VMMDEV, mouseYAbs);
+ GEN_CHECK_OFF(VMMDEV, fHostCursorRequested);
+ GEN_CHECK_OFF(VMMDEV, pDevInsR3);
+ GEN_CHECK_OFF(VMMDEV, pDevInsR0);
+ GEN_CHECK_OFF(VMMDEV, pDevInsRC);
+ GEN_CHECK_OFF(VMMDEV, IBase);
+ GEN_CHECK_OFF(VMMDEV, IPort);
+#ifdef VBOX_WITH_HGCM
+ GEN_CHECK_OFF(VMMDEV, IHGCMPort);
+#endif
+ GEN_CHECK_OFF(VMMDEV, pDrvBase);
+ GEN_CHECK_OFF(VMMDEV, pDrv);
+#ifdef VBOX_WITH_HGCM
+ GEN_CHECK_OFF(VMMDEV, pHGCMDrv);
+#endif
+ GEN_CHECK_OFF(VMMDEV, szMsg);
+ GEN_CHECK_OFF(VMMDEV, iMsg);
+ GEN_CHECK_OFF(VMMDEV, irq);
+ GEN_CHECK_OFF(VMMDEV, u32HostEventFlags);
+ GEN_CHECK_OFF(VMMDEV, u32GuestFilterMask);
+ GEN_CHECK_OFF(VMMDEV, u32NewGuestFilterMask);
+ GEN_CHECK_OFF(VMMDEV, fNewGuestFilterMask);
+ GEN_CHECK_OFF(VMMDEV, GCPhysVMMDevRAM);
+ GEN_CHECK_OFF(VMMDEV, pVMMDevRAMR3);
+ GEN_CHECK_OFF(VMMDEV, pVMMDevRAMR0);
+ GEN_CHECK_OFF(VMMDEV, pVMMDevRAMRC);
+ GEN_CHECK_OFF(VMMDEV, pVMMDevHeapR3);
+ GEN_CHECK_OFF(VMMDEV, GCPhysVMMDevHeap);
+ GEN_CHECK_OFF(VMMDEV, guestInfo);
+ GEN_CHECK_OFF(VMMDEV, guestCaps);
+ GEN_CHECK_OFF(VMMDEV, fu32AdditionsOk);
+ GEN_CHECK_OFF(VMMDEV, u32VideoAccelEnabled);
+ GEN_CHECK_OFF(VMMDEV, displayChangeData);
+ GEN_CHECK_OFF(VMMDEV, pCredentials);
+ GEN_CHECK_OFF(VMMDEV, cMbMemoryBalloon);
+ GEN_CHECK_OFF(VMMDEV, cMbMemoryBalloonLast);
+ GEN_CHECK_OFF(VMMDEV, cbGuestRAM);
+ GEN_CHECK_OFF(VMMDEV, idSession);
+ GEN_CHECK_OFF(VMMDEV, u32StatIntervalSize);
+ GEN_CHECK_OFF(VMMDEV, u32LastStatIntervalSize);
+ GEN_CHECK_OFF(VMMDEV, fLastSeamlessEnabled),
+ GEN_CHECK_OFF(VMMDEV, fSeamlessEnabled);
+ GEN_CHECK_OFF(VMMDEV, fVRDPEnabled);
+ GEN_CHECK_OFF(VMMDEV, uVRDPExperienceLevel);
+#ifdef VMMDEV_WITH_ALT_TIMESYNC
+ GEN_CHECK_OFF(VMMDEV, hostTime);
+ GEN_CHECK_OFF(VMMDEV, fTimesyncBackdoorLo);
+#endif
+ GEN_CHECK_OFF(VMMDEV, fGetHostTimeDisabled);
+ GEN_CHECK_OFF(VMMDEV, fBackdoorLogDisabled);
+ GEN_CHECK_OFF(VMMDEV, fKeepCredentials);
+ GEN_CHECK_OFF(VMMDEV, fHeapEnabled);
+#ifdef VBOX_WITH_HGCM
+ GEN_CHECK_OFF(VMMDEV, listHGCMCmd);
+ GEN_CHECK_OFF(VMMDEV, critsectHGCMCmdList);
+ GEN_CHECK_OFF(VMMDEV, u32HGCMEnabled);
+#endif
+ GEN_CHECK_OFF(VMMDEV, SharedFolders);
+ GEN_CHECK_OFF(VMMDEV, SharedFolders.Led);
+ GEN_CHECK_OFF(VMMDEV, SharedFolders.ILeds);
+ GEN_CHECK_OFF(VMMDEV, SharedFolders.pLedsConnector);
+ GEN_CHECK_OFF(VMMDEV, fCpuHotPlugEventsEnabled);
+ GEN_CHECK_OFF(VMMDEV, enmCpuHotPlugEvent);
+ GEN_CHECK_OFF(VMMDEV, idCpuCore);
+ GEN_CHECK_OFF(VMMDEV, idCpuPackage);
+ GEN_CHECK_OFF(VMMDEV, StatMemBalloonChunks);
+ GEN_CHECK_OFF(VMMDEV, fRZEnabled);
+ GEN_CHECK_OFF(VMMDEV, fTestingEnabled);
+ GEN_CHECK_OFF(VMMDEV, fTestingMMIO);
+ GEN_CHECK_OFF(VMMDEV, u32TestingHighTimestamp);
+ GEN_CHECK_OFF(VMMDEV, u32TestingCmd);
+ GEN_CHECK_OFF(VMMDEV, offTestingData);
+ GEN_CHECK_OFF(VMMDEV, TestingData);
+ GEN_CHECK_OFF(VMMDEV, TestingData.Value.u64Value);
+ GEN_CHECK_OFF(VMMDEV, TestingData.Value.u32Unit);
+ GEN_CHECK_OFF(VMMDEV, TestingData.Value.szName);
+ GEN_CHECK_OFF(VMMDEV, nsLastHeartbeatTS);
+ GEN_CHECK_OFF(VMMDEV, fFlatlined);
+ GEN_CHECK_OFF(VMMDEV, fHeartbeatActive);
+ GEN_CHECK_OFF(VMMDEV, cNsHeartbeatInterval);
+ GEN_CHECK_OFF(VMMDEV, cNsHeartbeatTimeout);
+ GEN_CHECK_OFF(VMMDEV, pFlatlinedTimer);
+
+#ifdef VBOX_WITH_BUSLOGIC
+ GEN_CHECK_SIZE(BUSLOGICDEVICE);
+ GEN_CHECK_OFF(BUSLOGICDEVICE, pBusLogicR3);
+ GEN_CHECK_OFF(BUSLOGICDEVICE, pBusLogicR0);
+ GEN_CHECK_OFF(BUSLOGICDEVICE, pBusLogicRC);
+ GEN_CHECK_OFF(BUSLOGICDEVICE, fPresent);
+ GEN_CHECK_OFF(BUSLOGICDEVICE, iLUN);
+ GEN_CHECK_OFF(BUSLOGICDEVICE, IBase);
+ GEN_CHECK_OFF(BUSLOGICDEVICE, IMediaPort);
+ GEN_CHECK_OFF(BUSLOGICDEVICE, IMediaExPort);
+ GEN_CHECK_OFF(BUSLOGICDEVICE, ILed);
+ GEN_CHECK_OFF(BUSLOGICDEVICE, pDrvBase);
+ GEN_CHECK_OFF(BUSLOGICDEVICE, pDrvMedia);
+ GEN_CHECK_OFF(BUSLOGICDEVICE, pDrvMediaEx);
+ GEN_CHECK_OFF(BUSLOGICDEVICE, Led);
+ GEN_CHECK_OFF(BUSLOGICDEVICE, cOutstandingRequests);
+
+ GEN_CHECK_SIZE(BUSLOGIC);
+ GEN_CHECK_OFF(BUSLOGIC, dev);
+ GEN_CHECK_OFF(BUSLOGIC, pDevInsR3);
+ GEN_CHECK_OFF(BUSLOGIC, pDevInsR0);
+ GEN_CHECK_OFF(BUSLOGIC, pDevInsRC);
+ GEN_CHECK_OFF(BUSLOGIC, IOPortBase);
+ GEN_CHECK_OFF(BUSLOGIC, MMIOBase);
+ GEN_CHECK_OFF(BUSLOGIC, regStatus);
+ GEN_CHECK_OFF(BUSLOGIC, regInterrupt);
+ GEN_CHECK_OFF(BUSLOGIC, regGeometry);
+ GEN_CHECK_OFF(BUSLOGIC, LocalRam);
+ GEN_CHECK_OFF(BUSLOGIC, uOperationCode);
+ GEN_CHECK_OFF(BUSLOGIC, aCommandBuffer);
+ GEN_CHECK_OFF(BUSLOGIC, aCommandBuffer[BUSLOGIC_COMMAND_SIZE_MAX]);
+ GEN_CHECK_OFF(BUSLOGIC, iParameter);
+ GEN_CHECK_OFF(BUSLOGIC, cbCommandParametersLeft);
+ GEN_CHECK_OFF(BUSLOGIC, fUseLocalRam);
+ GEN_CHECK_OFF(BUSLOGIC, aReplyBuffer);
+ GEN_CHECK_OFF(BUSLOGIC, aReplyBuffer[BUSLOGIC_REPLY_SIZE_MAX]);
+ GEN_CHECK_OFF(BUSLOGIC, iReply);
+ GEN_CHECK_OFF(BUSLOGIC, cbReplyParametersLeft);
+ GEN_CHECK_OFF(BUSLOGIC, fIRQEnabled);
+ GEN_CHECK_OFF(BUSLOGIC, cMailbox);
+ GEN_CHECK_OFF(BUSLOGIC, GCPhysAddrMailboxOutgoingBase);
+ GEN_CHECK_OFF(BUSLOGIC, uMailboxOutgoingPositionCurrent);
+ GEN_CHECK_OFF(BUSLOGIC, cMailboxesReady);
+ GEN_CHECK_OFF(BUSLOGIC, fNotificationSent);
+ GEN_CHECK_OFF(BUSLOGIC, GCPhysAddrMailboxIncomingBase);
+ GEN_CHECK_OFF(BUSLOGIC, uMailboxIncomingPositionCurrent);
+ GEN_CHECK_OFF(BUSLOGIC, fStrictRoundRobinMode);
+ GEN_CHECK_OFF(BUSLOGIC, fExtendedLunCCBFormat);
+ GEN_CHECK_OFF(BUSLOGIC, pNotifierQueueR3);
+ GEN_CHECK_OFF(BUSLOGIC, pNotifierQueueR0);
+ GEN_CHECK_OFF(BUSLOGIC, pNotifierQueueRC);
+ GEN_CHECK_OFF(BUSLOGIC, CritSectIntr);
+ GEN_CHECK_OFF(BUSLOGIC, aDeviceStates);
+ GEN_CHECK_OFF(BUSLOGIC, aDeviceStates[BUSLOGIC_MAX_DEVICES-1]);
+ GEN_CHECK_OFF(BUSLOGIC, IBase);
+ GEN_CHECK_OFF(BUSLOGIC, ILeds);
+ GEN_CHECK_OFF(BUSLOGIC, pLedsConnector);
+ GEN_CHECK_OFF(BUSLOGIC, pMediaNotify);
+ GEN_CHECK_OFF(BUSLOGIC, fSignalIdle);
+ GEN_CHECK_OFF(BUSLOGIC, fWrkThreadSleeping);
+ GEN_CHECK_OFF(BUSLOGIC, pSupDrvSession);
+ GEN_CHECK_OFF(BUSLOGIC, hEvtProcess);
+ GEN_CHECK_OFF(BUSLOGIC, paGCPhysAddrCCBRedo);
+ GEN_CHECK_OFF(BUSLOGIC, cReqsRedo);
+# ifdef LOG_ENABLED
+ GEN_CHECK_OFF(BUSLOGIC, cInMailboxesReady);
+# endif
+#endif /* VBOX_WITH_BUSLOGIC */
+
+#ifdef VBOX_WITH_LSILOGIC
+ GEN_CHECK_SIZE(LSILOGICSCSI);
+ GEN_CHECK_OFF(LSILOGICSCSI, PciDev);
+ GEN_CHECK_OFF(LSILOGICSCSI, pDevInsR3);
+ GEN_CHECK_OFF(LSILOGICSCSI, pDevInsR0);
+ GEN_CHECK_OFF(LSILOGICSCSI, pDevInsRC);
+ GEN_CHECK_OFF(LSILOGICSCSI, fGCEnabled);
+ GEN_CHECK_OFF(LSILOGICSCSI, fR0Enabled);
+ GEN_CHECK_OFF(LSILOGICSCSI, enmState);
+ GEN_CHECK_OFF(LSILOGICSCSI, enmWhoInit);
+ GEN_CHECK_OFF(LSILOGICSCSI, enmDoorbellState);
+ GEN_CHECK_OFF(LSILOGICSCSI, fDiagnosticEnabled);
+ GEN_CHECK_OFF(LSILOGICSCSI, fNotificationSent);
+ GEN_CHECK_OFF(LSILOGICSCSI, fEventNotificationEnabled);
+ GEN_CHECK_OFF(LSILOGICSCSI, fDiagRegsEnabled);
+ GEN_CHECK_OFF(LSILOGICSCSI, pNotificationQueueR3);
+ GEN_CHECK_OFF(LSILOGICSCSI, pNotificationQueueR0);
+ GEN_CHECK_OFF(LSILOGICSCSI, pNotificationQueueRC);
+ GEN_CHECK_OFF(LSILOGICSCSI, cDeviceStates);
+ GEN_CHECK_OFF(LSILOGICSCSI, paDeviceStates);
+ GEN_CHECK_OFF(LSILOGICSCSI, GCPhysMMIOBase);
+ GEN_CHECK_OFF(LSILOGICSCSI, IOPortBase);
+ GEN_CHECK_OFF(LSILOGICSCSI, uInterruptMask);
+ GEN_CHECK_OFF(LSILOGICSCSI, uInterruptStatus);
+ GEN_CHECK_OFF(LSILOGICSCSI, aMessage);
+ GEN_CHECK_OFF(LSILOGICSCSI, aMessage[sizeof(MptConfigurationRequest)-1]);
+ GEN_CHECK_OFF(LSILOGICSCSI, iMessage);
+ GEN_CHECK_OFF(LSILOGICSCSI, cMessage);
+ GEN_CHECK_OFF(LSILOGICSCSI, ReplyBuffer);
+ GEN_CHECK_OFF(LSILOGICSCSI, uNextReplyEntryRead);
+ GEN_CHECK_OFF(LSILOGICSCSI, cReplySize);
+ GEN_CHECK_OFF(LSILOGICSCSI, u16IOCFaultCode);
+ GEN_CHECK_OFF(LSILOGICSCSI, u32HostMFAHighAddr);
+ GEN_CHECK_OFF(LSILOGICSCSI, u32SenseBufferHighAddr);
+ GEN_CHECK_OFF(LSILOGICSCSI, cMaxDevices);
+ GEN_CHECK_OFF(LSILOGICSCSI, cMaxBuses);
+ GEN_CHECK_OFF(LSILOGICSCSI, cbReplyFrame);
+ GEN_CHECK_OFF(LSILOGICSCSI, iDiagnosticAccess);
+ GEN_CHECK_OFF(LSILOGICSCSI, cReplyQueueEntries);
+ GEN_CHECK_OFF(LSILOGICSCSI, cRequestQueueEntries);
+ GEN_CHECK_OFF(LSILOGICSCSI, ReplyPostQueueCritSect);
+ GEN_CHECK_OFF(LSILOGICSCSI, ReplyFreeQueueCritSect);
+ GEN_CHECK_OFF(LSILOGICSCSI, RequestQueueCritSect);
+ GEN_CHECK_OFF(LSILOGICSCSI, ReplyFreeQueueWriteCritSect);
+ GEN_CHECK_OFF(LSILOGICSCSI, pReplyFreeQueueBaseR3);
+ GEN_CHECK_OFF(LSILOGICSCSI, pReplyPostQueueBaseR3);
+ GEN_CHECK_OFF(LSILOGICSCSI, pRequestQueueBaseR3);
+ GEN_CHECK_OFF(LSILOGICSCSI, pReplyFreeQueueBaseR0);
+ GEN_CHECK_OFF(LSILOGICSCSI, pReplyPostQueueBaseR0);
+ GEN_CHECK_OFF(LSILOGICSCSI, pRequestQueueBaseR0);
+ GEN_CHECK_OFF(LSILOGICSCSI, pReplyFreeQueueBaseRC);
+ GEN_CHECK_OFF(LSILOGICSCSI, pReplyPostQueueBaseRC);
+ GEN_CHECK_OFF(LSILOGICSCSI, pRequestQueueBaseRC);
+ GEN_CHECK_OFF(LSILOGICSCSI, uReplyFreeQueueNextEntryFreeWrite);
+ GEN_CHECK_OFF(LSILOGICSCSI, uReplyFreeQueueNextAddressRead);
+ GEN_CHECK_OFF(LSILOGICSCSI, uReplyPostQueueNextEntryFreeWrite);
+ GEN_CHECK_OFF(LSILOGICSCSI, uReplyPostQueueNextAddressRead);
+ GEN_CHECK_OFF(LSILOGICSCSI, uRequestQueueNextEntryFreeWrite);
+ GEN_CHECK_OFF(LSILOGICSCSI, uRequestQueueNextAddressRead);
+ GEN_CHECK_OFF(LSILOGICSCSI, u16NextHandle);
+ GEN_CHECK_OFF(LSILOGICSCSI, enmCtrlType);
+ GEN_CHECK_OFF(LSILOGICSCSI, IBase);
+ GEN_CHECK_OFF(LSILOGICSCSI, ILeds);
+ GEN_CHECK_OFF(LSILOGICSCSI, pLedsConnector);
+ GEN_CHECK_OFF(LSILOGICSCSI, pMediaNotify);
+ GEN_CHECK_OFF(LSILOGICSCSI, pConfigurationPages);
+ GEN_CHECK_OFF(LSILOGICSCSI, fSignalIdle);
+ GEN_CHECK_OFF(LSILOGICSCSI, fRedo);
+ GEN_CHECK_OFF(LSILOGICSCSI, fWrkThreadSleeping);
+ GEN_CHECK_OFF(LSILOGICSCSI, pTasksRedoHead);
+ GEN_CHECK_OFF(LSILOGICSCSI, u32DiagMemAddr);
+ GEN_CHECK_OFF(LSILOGICSCSI, cbMemRegns);
+ GEN_CHECK_OFF(LSILOGICSCSI, ListMemRegns);
+ GEN_CHECK_OFF(LSILOGICSCSI, pSupDrvSession);
+ GEN_CHECK_OFF(LSILOGICSCSI, pThreadWrk);
+ GEN_CHECK_OFF(LSILOGICSCSI, hEvtProcess);
+#endif /* VBOX_WITH_LSILOGIC */
+
+ GEN_CHECK_SIZE(HPET);
+ GEN_CHECK_OFF(HPET, pDevInsR3);
+ GEN_CHECK_OFF(HPET, pDevInsR0);
+ GEN_CHECK_OFF(HPET, pDevInsRC);
+ GEN_CHECK_OFF(HPET, u64HpetOffset);
+ GEN_CHECK_OFF(HPET, u32Capabilities);
+ GEN_CHECK_OFF(HPET, u32Period);
+ GEN_CHECK_OFF(HPET, u64HpetConfig);
+ GEN_CHECK_OFF(HPET, u64Isr);
+ GEN_CHECK_OFF(HPET, u64HpetCounter);
+ GEN_CHECK_OFF(HPET, CritSect);
+ GEN_CHECK_OFF(HPET, fIch9);
+
+ GEN_CHECK_SIZE(HPETTIMER);
+ GEN_CHECK_OFF(HPETTIMER, pTimerR3);
+ GEN_CHECK_OFF(HPETTIMER, pHpetR3);
+ GEN_CHECK_OFF(HPETTIMER, pTimerR0);
+ GEN_CHECK_OFF(HPETTIMER, pHpetR0);
+ GEN_CHECK_OFF(HPETTIMER, pTimerRC);
+ GEN_CHECK_OFF(HPETTIMER, pHpetRC);
+ GEN_CHECK_OFF(HPETTIMER, idxTimer);
+ GEN_CHECK_OFF(HPETTIMER, u64Config);
+ GEN_CHECK_OFF(HPETTIMER, u64Cmp);
+ GEN_CHECK_OFF(HPETTIMER, u64Fsb);
+ GEN_CHECK_OFF(HPETTIMER, u64Period);
+ GEN_CHECK_OFF(HPETTIMER, u8Wrap);
+
+ GEN_CHECK_SIZE(AC97DRIVER);
+ GEN_CHECK_OFF(AC97DRIVER, Node);
+ GEN_CHECK_OFF(AC97DRIVER, pAC97State);
+ GEN_CHECK_OFF(AC97DRIVER, fFlags);
+ GEN_CHECK_OFF(AC97DRIVER, uLUN);
+ GEN_CHECK_OFF(AC97DRIVER, fAttached);
+ GEN_CHECK_OFF(AC97DRIVER, pConnector);
+ GEN_CHECK_OFF(AC97DRIVER, LineIn);
+ GEN_CHECK_OFF(AC97DRIVER, MicIn);
+ GEN_CHECK_OFF(AC97DRIVER, Out);
+
+ GEN_CHECK_SIZE(AC97STATE);
+ GEN_CHECK_OFF(AC97STATE, CritSect);
+ GEN_CHECK_OFF(AC97STATE, pDevInsR3);
+ GEN_CHECK_OFF(AC97STATE, pDevInsR0);
+ GEN_CHECK_OFF(AC97STATE, pDevInsRC);
+ GEN_CHECK_OFF(AC97STATE, fRZEnabled);
+ GEN_CHECK_OFF(AC97STATE, glob_cnt);
+ GEN_CHECK_OFF(AC97STATE, glob_sta);
+ GEN_CHECK_OFF(AC97STATE, cas);
+ GEN_CHECK_OFF(AC97STATE, last_samp);
+ GEN_CHECK_OFF(AC97STATE, mixer_data);
+ GEN_CHECK_OFF(AC97STATE, aStreams);
+ GEN_CHECK_OFF(AC97STATE, uTimerHz);
+ GEN_CHECK_OFF(AC97STATE, pTimerRC);
+ GEN_CHECK_OFF(AC97STATE, pTimerR3);
+ GEN_CHECK_OFF(AC97STATE, pTimerR0);
+#ifdef VBOX_WITH_STATISTICS
+ GEN_CHECK_OFF(AC97STATE, StatTimer);
+ GEN_CHECK_OFF(AC97STATE, StatIn);
+ GEN_CHECK_OFF(AC97STATE, StatOut);
+ GEN_CHECK_OFF(AC97STATE, StatBytesRead);
+ GEN_CHECK_OFF(AC97STATE, StatBytesWritten);
+#endif
+ GEN_CHECK_OFF(AC97STATE, lstDrv);
+ GEN_CHECK_OFF(AC97STATE, pMixer);
+ GEN_CHECK_OFF(AC97STATE, pSinkOut);
+ GEN_CHECK_OFF(AC97STATE, pSinkLineIn);
+ GEN_CHECK_OFF(AC97STATE, pSinkMicIn);
+ GEN_CHECK_OFF(AC97STATE, silence);
+ GEN_CHECK_OFF(AC97STATE, bup_flag);
+ GEN_CHECK_OFF(AC97STATE, IBase);
+ GEN_CHECK_OFF(AC97STATE, IOPortBase);
+ GEN_CHECK_OFF(AC97STATE, uCodecModel);
+
+ GEN_CHECK_SIZE(AC97STREAM);
+ GEN_CHECK_OFF(AC97STREAM, pAC97State);
+
+ GEN_CHECK_SIZE(AC97STREAMSTATE);
+ GEN_CHECK_OFF(AC97STREAMSTATE, CritSect);
+ GEN_CHECK_OFF(AC97STREAMSTATE, pCircBuf);
+ GEN_CHECK_OFF(AC97STREAMSTATE, tsTransferLast);
+
+ GEN_CHECK_SIZE(HDADRIVERSTREAM);
+ GEN_CHECK_OFF(HDADRIVERSTREAM, pMixStrm);
+
+ GEN_CHECK_SIZE(HDADRIVER);
+ GEN_CHECK_OFF(HDADRIVER, Node);
+ GEN_CHECK_OFF(HDADRIVER, pHDAState);
+ GEN_CHECK_OFF(HDADRIVER, fFlags);
+ GEN_CHECK_OFF(HDADRIVER, uLUN);
+ GEN_CHECK_OFF(HDADRIVER, fAttached);
+ GEN_CHECK_OFF(HDADRIVER, pConnector);
+ GEN_CHECK_OFF(HDADRIVER, LineIn);
+#ifdef VBOX_WITH_HDA_MIC_IN
+ GEN_CHECK_OFF(HDADRIVER, MicIn);
+#endif
+ GEN_CHECK_OFF(HDADRIVER, Front);
+#ifdef VBOX_WITH_HDA_51_SURROUND
+ GEN_CHECK_OFF(HDADRIVER, CenterLFE);
+ GEN_CHECK_OFF(HDADRIVER, Rear);
+#endif
+
+ GEN_CHECK_SIZE(HDABDLESTATE);
+ GEN_CHECK_OFF(HDABDLESTATE, u32BDLIndex);
+ GEN_CHECK_OFF(HDABDLESTATE, cbBelowFIFOW);
+ GEN_CHECK_OFF(HDABDLESTATE, u32BufOff);
+
+ GEN_CHECK_SIZE(HDABDLEDESC);
+ GEN_CHECK_OFF(HDABDLEDESC, u64BufAddr);
+ GEN_CHECK_OFF(HDABDLEDESC, u32BufSize);
+ GEN_CHECK_OFF(HDABDLEDESC, fFlags);
+
+ GEN_CHECK_SIZE(HDABDLE);
+ GEN_CHECK_OFF(HDABDLE, Desc);
+ GEN_CHECK_OFF(HDABDLE, State);
+
+ GEN_CHECK_SIZE(HDASTREAMMAP);
+
+ GEN_CHECK_SIZE(HDASTREAMSTATE);
+ GEN_CHECK_OFF(HDASTREAMSTATE, uCurBDLE);
+ GEN_CHECK_OFF(HDASTREAMSTATE, fInReset);
+ GEN_CHECK_OFF(HDASTREAMSTATE, Mapping);
+ GEN_CHECK_OFF(HDASTREAMSTATE, BDLE);
+ GEN_CHECK_OFF(HDASTREAMSTATE, pCircBuf);
+
+ GEN_CHECK_SIZE(HDASTREAMDBGINFORT);
+
+ GEN_CHECK_SIZE(HDASTREAMDBGINFO);
+ GEN_CHECK_OFF(HDASTREAMDBGINFO, Runtime);
+
+ GEN_CHECK_SIZE(HDASTREAM);
+ GEN_CHECK_OFF(HDASTREAM, u8SD);
+ GEN_CHECK_OFF(HDASTREAM, u64BDLBase);
+ GEN_CHECK_OFF(HDASTREAM, u16FMT);
+ GEN_CHECK_OFF(HDASTREAM, u16FIFOS);
+ GEN_CHECK_OFF(HDASTREAM, u16LVI);
+ GEN_CHECK_OFF(HDASTREAM, State);
+ GEN_CHECK_OFF(HDASTREAM, Dbg);
+ GEN_CHECK_OFF(HDASTREAM, CritSect);
+
+ GEN_CHECK_SIZE(HDASTATE);
+ GEN_CHECK_OFF(HDASTATE, PciDev);
+ GEN_CHECK_OFF(HDASTATE, pDevInsR3);
+ GEN_CHECK_OFF(HDASTATE, pDevInsR0);
+ GEN_CHECK_OFF(HDASTATE, pDevInsRC);
+ GEN_CHECK_OFF(HDASTATE, IBase);
+ GEN_CHECK_OFF(HDASTATE, MMIOBaseAddr);
+ GEN_CHECK_OFF(HDASTATE, au32Regs[0]);
+ GEN_CHECK_OFF(HDASTATE, au32Regs[HDA_NUM_REGS]);
+ GEN_CHECK_OFF(HDASTATE, aStreams);
+ GEN_CHECK_OFF(HDASTATE, aTags);
+ GEN_CHECK_OFF(HDASTATE, u64CORBBase);
+ GEN_CHECK_OFF(HDASTATE, u64RIRBBase);
+ GEN_CHECK_OFF(HDASTATE, u64DPBase);
+ GEN_CHECK_OFF(HDASTATE, pu32CorbBuf);
+ GEN_CHECK_OFF(HDASTATE, cbCorbBuf);
+ GEN_CHECK_OFF(HDASTATE, pu64RirbBuf);
+ GEN_CHECK_OFF(HDASTATE, cbRirbBuf);
+ GEN_CHECK_OFF(HDASTATE, fRZEnabled);
+#ifdef VBOX_WITH_STATISTICS
+# ifndef VBOX_WITH_AUDIO_CALLBACKS
+ GEN_CHECK_OFF(HDASTATE, StatTimer);
+# endif
+ GEN_CHECK_OFF(HDASTATE, StatBytesRead);
+ GEN_CHECK_OFF(HDASTATE, StatBytesWritten);
+#endif /* VBOX_WITH_STATISTICS */
+ GEN_CHECK_OFF(HDASTATE, pCodec);
+ GEN_CHECK_OFF(HDASTATE, lstDrv);
+ GEN_CHECK_OFF(HDASTATE, pMixer);
+ GEN_CHECK_OFF(HDASTATE, SinkFront);
+#ifdef VBOX_WITH_HDA_51_SURROUND
+ GEN_CHECK_OFF(HDASTATE, SinkCenterLFE);
+ GEN_CHECK_OFF(HDASTATE, SinkRear);
+#endif
+ GEN_CHECK_OFF(HDASTATE, SinkLineIn);
+#ifdef VBOX_WITH_HDA_MIC_IN
+ GEN_CHECK_OFF(HDASTATE, SinkMicIn);
+#endif
+ GEN_CHECK_OFF(HDASTATE, u64WalClk);
+ GEN_CHECK_OFF(HDASTATE, u16RespIntCnt);
+ GEN_CHECK_OFF(HDASTATE, cPosAdjustFrames);
+ GEN_CHECK_OFF(HDASTATE, u8IRQL);
+
+#ifdef VBOX_WITH_NVME_IMPL
+ GEN_CHECK_SIZE(NVMEQUEUEHDR);
+ GEN_CHECK_OFF(NVMEQUEUEHDR, u16Id);
+ GEN_CHECK_OFF(NVMEQUEUEHDR, cEntries);
+ GEN_CHECK_OFF(NVMEQUEUEHDR, enmState);
+ GEN_CHECK_OFF(NVMEQUEUEHDR, GCPhysBase);
+ GEN_CHECK_OFF(NVMEQUEUEHDR, cbEntry);
+ GEN_CHECK_OFF(NVMEQUEUEHDR, idxHead);
+ GEN_CHECK_OFF(NVMEQUEUEHDR, idxTail);
+ GEN_CHECK_OFF(NVMEQUEUEHDR, fPhysCont);
+ GEN_CHECK_OFF(NVMEQUEUEHDR, enmType);
+
+ GEN_CHECK_SIZE(NVMEQUEUESUBM);
+ GEN_CHECK_OFF(NVMEQUEUESUBM, Hdr);
+ GEN_CHECK_OFF(NVMEQUEUESUBM, u16CompletionQueueId);
+ GEN_CHECK_OFF(NVMEQUEUESUBM, enmPriority);
+ GEN_CHECK_OFF(NVMEQUEUESUBM, hEvtProcess);
+ GEN_CHECK_OFF(NVMEQUEUESUBM, pWrkThrdR3);
+ GEN_CHECK_OFF(NVMEQUEUESUBM, NdLstWrkThrdAssgnd);
+ GEN_CHECK_OFF(NVMEQUEUESUBM, cReqsActive);
+
+ GEN_CHECK_SIZE(NVMEQUEUECOMP);
+ GEN_CHECK_OFF(NVMEQUEUECOMP, Hdr);
+ GEN_CHECK_OFF(NVMEQUEUECOMP, fIntrEnabled);
+ GEN_CHECK_OFF(NVMEQUEUECOMP, u32IntrVec);
+ GEN_CHECK_OFF(NVMEQUEUECOMP, cSubmQueuesRef);
+ GEN_CHECK_OFF(NVMEQUEUECOMP, cWaiters);
+ GEN_CHECK_OFF(NVMEQUEUECOMP, LstCompletionsWaiting);
+ GEN_CHECK_OFF(NVMEQUEUECOMP, hMtx);
+
+ GEN_CHECK_SIZE(NVME);
+ GEN_CHECK_OFF(NVME, PciDev);
+ GEN_CHECK_OFF(NVME, pDevInsR3);
+ GEN_CHECK_OFF(NVME, pDevInsR0);
+ GEN_CHECK_OFF(NVME, pDevInsRC);
+ GEN_CHECK_OFF(NVME, IBase);
+ GEN_CHECK_OFF(NVME, ILeds);
+ GEN_CHECK_OFF(NVME, pLedsConnector);
+ GEN_CHECK_OFF(NVME, pSupDrvSession);
+ GEN_CHECK_OFF(NVME, GCPhysMMIO);
+ GEN_CHECK_OFF(NVME, IOPortBase);
+ GEN_CHECK_OFF(NVME, cQueuesSubmMax);
+ GEN_CHECK_OFF(NVME, cQueuesCompMax);
+ GEN_CHECK_OFF(NVME, cQueueEntriesMax);
+ GEN_CHECK_OFF(NVME, cTimeoutMax);
+ GEN_CHECK_OFF(NVME, cWrkThrdsMax);
+ GEN_CHECK_OFF(NVME, cCompQueuesWaitersMax);
+ GEN_CHECK_OFF(NVME, cNamespaces);
+ GEN_CHECK_OFF(NVME, szSerialNumber);
+ GEN_CHECK_OFF(NVME, szModelNumber);
+ GEN_CHECK_OFF(NVME, szFirmwareRevision);
+ GEN_CHECK_OFF(NVME, fRCEnabled);
+ GEN_CHECK_OFF(NVME, fR0Enabled);
+ GEN_CHECK_OFF(NVME, enmState);
+ GEN_CHECK_OFF(NVME, u32IntrMask);
+ GEN_CHECK_OFF(NVME, aIntrVecs);
+ GEN_CHECK_OFF(NVME, u32IoCompletionQueueEntrySize);
+ GEN_CHECK_OFF(NVME, u32IoSubmissionQueueEntrySize);
+ GEN_CHECK_OFF(NVME, uShutdwnNotifierLast);
+ GEN_CHECK_OFF(NVME, uAmsSet);
+ GEN_CHECK_OFF(NVME, uMpsSet);
+ GEN_CHECK_OFF(NVME, uCssSet);
+ GEN_CHECK_OFF(NVME, u32RegIdx);
+ GEN_CHECK_OFF(NVME, cbPage);
+ GEN_CHECK_OFF(NVME, paQueuesSubmR3);
+ GEN_CHECK_OFF(NVME, paQueuesCompR3);
+ GEN_CHECK_OFF(NVME, paQueuesSubmR0);
+ GEN_CHECK_OFF(NVME, paQueuesCompR0);
+ GEN_CHECK_OFF(NVME, paQueuesSubmRC);
+ GEN_CHECK_OFF(NVME, paQueuesCompRC);
+ GEN_CHECK_OFF(NVME, pvCtrlMemBufR3);
+ GEN_CHECK_OFF(NVME, GCPhysCtrlMemBuf);
+ GEN_CHECK_OFF(NVME, cbCtrlMemBuf);
+ GEN_CHECK_OFF(NVME, u32CtrlMemBufSz);
+ GEN_CHECK_OFF(NVME, pWakeQueueR3);
+ GEN_CHECK_OFF(NVME, pWakeQueueR0);
+ GEN_CHECK_OFF(NVME, pWakeQueueRC);
+ GEN_CHECK_OFF(NVME, cAsyncEvtReqsMax);
+ GEN_CHECK_OFF(NVME, CritSectAsyncEvtReqs);
+ GEN_CHECK_OFF(NVME, paAsyncEvtReqCids);
+ GEN_CHECK_OFF(NVME, paNamespaces);
+ GEN_CHECK_OFF(NVME, cWrkThrdsCur);
+ GEN_CHECK_OFF(NVME, cWrkThrdsActive);
+ GEN_CHECK_OFF(NVME, LstWrkThrds);
+ GEN_CHECK_OFF(NVME, CritSectWrkThrds);
+ GEN_CHECK_OFF(NVME, fSignalIdle);
+# ifdef VBOX_WITH_STATISTICS
+ GEN_CHECK_OFF(NVME, aStatMemXfer[0]);
+ GEN_CHECK_OFF(NVME, aStatMemXfer[NVME_CMBSZ_SUPP_BIT_IDX_MAX]);
+# endif
+#endif
+
+#ifdef VBOX_WITH_IOMMU_AMD
+# ifdef IOMMU_WITH_DTE_CACHE
+ GEN_CHECK_SIZE(DTECACHE);
+# endif
+# ifdef IOMMU_WITH_DTE_CACHE
+ GEN_CHECK_SIZE(IRTECACHE);
+# endif
+ GEN_CHECK_SIZE(IOMMU);
+ GEN_CHECK_OFF(IOMMU, idxIommu);
+ GEN_CHECK_OFF(IOMMU, u32Magic);
+ GEN_CHECK_OFF(IOMMU, hMmio);
+ GEN_CHECK_OFF(IOMMU, hEvtCmdThread);
+ GEN_CHECK_OFF(IOMMU, fCmdThreadSignaled);
+# ifdef IOMMU_WITH_DTE_CACHE
+ GEN_CHECK_OFF(IOMMU, CritSectCache);
+ GEN_CHECK_OFF(IOMMU, aDeviceIds);
+ GEN_CHECK_OFF(IOMMU, aDteCache);
+# endif
+# ifdef IOMMU_WITH_IRTE_CACHE
+ GEN_CHECK_OFF(IOMMU, aIrteCache);
+# endif
+ GEN_CHECK_OFF(IOMMU, IommuBar);
+ GEN_CHECK_OFF(IOMMU, aDevTabBaseAddrs);
+ GEN_CHECK_OFF(IOMMU, CmdBufBaseAddr);
+ GEN_CHECK_OFF(IOMMU, EvtLogBaseAddr);
+ GEN_CHECK_OFF(IOMMU, Ctrl);
+ GEN_CHECK_OFF(IOMMU, ExclRangeBaseAddr);
+ GEN_CHECK_OFF(IOMMU, ExclRangeLimit);
+ GEN_CHECK_OFF(IOMMU, ExtFeat);
+ GEN_CHECK_OFF(IOMMU, PprLogBaseAddr);
+ GEN_CHECK_OFF(IOMMU, HwEvtHi);
+ GEN_CHECK_OFF(IOMMU, HwEvtLo);
+ GEN_CHECK_OFF(IOMMU, HwEvtStatus);
+ GEN_CHECK_OFF(IOMMU, GALogBaseAddr);
+ GEN_CHECK_OFF(IOMMU, GALogTailAddr);
+ GEN_CHECK_OFF(IOMMU, PprLogBBaseAddr);
+ GEN_CHECK_OFF(IOMMU, EvtLogBBaseAddr);
+ GEN_CHECK_OFF(IOMMU, DevSpecificFeat);
+ GEN_CHECK_OFF(IOMMU, DevSpecificCtrl);
+ GEN_CHECK_OFF(IOMMU, DevSpecificStatus);
+ GEN_CHECK_OFF(IOMMU, MiscInfo);
+ GEN_CHECK_OFF(IOMMU, PerfOptCtrl);
+ GEN_CHECK_OFF(IOMMU, XtGenIntrCtrl);
+ GEN_CHECK_OFF(IOMMU, XtPprIntrCtrl);
+ GEN_CHECK_OFF(IOMMU, XtGALogIntrCtrl);
+ GEN_CHECK_OFF(IOMMU, aMarcApers);
+ GEN_CHECK_OFF(IOMMU, RsvdReg);
+ GEN_CHECK_OFF(IOMMU, CmdBufHeadPtr);
+ GEN_CHECK_OFF(IOMMU, CmdBufTailPtr);
+ GEN_CHECK_OFF(IOMMU, EvtLogHeadPtr);
+ GEN_CHECK_OFF(IOMMU, EvtLogTailPtr);
+ GEN_CHECK_OFF(IOMMU, Status);
+ GEN_CHECK_OFF(IOMMU, PprLogHeadPtr);
+ GEN_CHECK_OFF(IOMMU, PprLogTailPtr);
+ GEN_CHECK_OFF(IOMMU, GALogHeadPtr);
+ GEN_CHECK_OFF(IOMMU, GALogTailPtr);
+ GEN_CHECK_OFF(IOMMU, PprLogBHeadPtr);
+ GEN_CHECK_OFF(IOMMU, PprLogBTailPtr);
+ GEN_CHECK_OFF(IOMMU, EvtLogBHeadPtr);
+ GEN_CHECK_OFF(IOMMU, EvtLogBTailPtr);
+ GEN_CHECK_OFF(IOMMU, PprLogAutoResp);
+ GEN_CHECK_OFF(IOMMU, PprLogOverflowEarly);
+ GEN_CHECK_OFF(IOMMU, PprLogBOverflowEarly);
+# ifdef VBOX_WITH_STATISTICS
+ GEN_CHECK_OFF(IOMMU, StatMmioReadR3);
+ GEN_CHECK_OFF(IOMMU, StatMmioReadRZ);
+ GEN_CHECK_OFF(IOMMU, StatMmioWriteR3);
+ GEN_CHECK_OFF(IOMMU, StatMmioWriteRZ);
+ GEN_CHECK_OFF(IOMMU, StatMsiRemapR3);
+ GEN_CHECK_OFF(IOMMU, StatMsiRemapRZ);
+ GEN_CHECK_OFF(IOMMU, StatMemReadR3);
+ GEN_CHECK_OFF(IOMMU, StatMemReadRZ);
+ GEN_CHECK_OFF(IOMMU, StatMemWriteR3);
+ GEN_CHECK_OFF(IOMMU, StatMemWriteRZ);
+ GEN_CHECK_OFF(IOMMU, StatMemBulkReadR3);
+ GEN_CHECK_OFF(IOMMU, StatMemBulkReadRZ);
+ GEN_CHECK_OFF(IOMMU, StatMemBulkWriteR3);
+ GEN_CHECK_OFF(IOMMU, StatMemBulkWriteRZ);
+ GEN_CHECK_OFF(IOMMU, StatCmd);
+ GEN_CHECK_OFF(IOMMU, StatCmdCompWait);
+ GEN_CHECK_OFF(IOMMU, StatCmdInvDte);
+ GEN_CHECK_OFF(IOMMU, StatCmdInvIommuPages);
+ GEN_CHECK_OFF(IOMMU, StatCmdInvIotlbPages);
+ GEN_CHECK_OFF(IOMMU, StatCmdInvIntrTable);
+ GEN_CHECK_OFF(IOMMU, StatCmdPrefIommuPages);
+ GEN_CHECK_OFF(IOMMU, StatCmdCompletePprReq);
+ GEN_CHECK_OFF(IOMMU, StatCmdInvIommuAll);
+ GEN_CHECK_OFF(IOMMU, StatIotlbeCached);
+ GEN_CHECK_OFF(IOMMU, StatIotlbeLazyEvictReuse);
+ GEN_CHECK_OFF(IOMMU, StatProfDteLookup);
+ GEN_CHECK_OFF(IOMMU, StatProfIotlbeLookup);
+ GEN_CHECK_OFF(IOMMU, StatProfIrteLookup);
+ GEN_CHECK_OFF(IOMMU, StatProfIrteCacheLookup);
+ GEN_CHECK_OFF(IOMMU, StatAccessCacheHit);
+ GEN_CHECK_OFF(IOMMU, StatAccessCacheHitFull);
+ GEN_CHECK_OFF(IOMMU, StatAccessCacheMiss);
+ GEN_CHECK_OFF(IOMMU, StatAccessCacheNonContig);
+ GEN_CHECK_OFF(IOMMU, StatAccessCachePermDenied);
+ GEN_CHECK_OFF(IOMMU, StatAccessDteNonContig);
+ GEN_CHECK_OFF(IOMMU, StatAccessDtePermDenied);
+ GEN_CHECK_OFF(IOMMU, StatIntrCacheHit);
+ GEN_CHECK_OFF(IOMMU, StatIntrCacheMiss);
+# endif
+#endif
+
+#ifdef VBOX_WITH_IOMMU_INTEL
+ GEN_CHECK_SIZE(DMAR);
+ GEN_CHECK_OFF(DMAR, idxIommu);
+ GEN_CHECK_OFF(DMAR, abRegs0);
+ GEN_CHECK_OFF(DMAR, abRegs1);
+ GEN_CHECK_OFF(DMAR, uIrtaReg);
+ GEN_CHECK_OFF(DMAR, uRtaddrReg);
+ GEN_CHECK_OFF(DMAR, uVerReg);
+ GEN_CHECK_OFF(DMAR, fCapReg);
+ GEN_CHECK_OFF(DMAR, fExtCapReg);
+ GEN_CHECK_OFF(DMAR, fHawBaseMask);
+ GEN_CHECK_OFF(DMAR, fMgawInvMask);
+ GEN_CHECK_OFF(DMAR, cMaxPagingLevel);
+ GEN_CHECK_OFF(DMAR, fPermValidMask);
+ GEN_CHECK_OFF(DMAR, hEvtInvQueue);
+ GEN_CHECK_OFF(DMAR, enmDiag);
+ GEN_CHECK_OFF(DMAR, hMmio);
+# ifdef VBOX_WITH_STATISTICS
+ GEN_CHECK_OFF(DMAR, StatMmioReadR3);
+ GEN_CHECK_OFF(DMAR, StatMmioReadRZ);
+ GEN_CHECK_OFF(DMAR, StatMmioWriteR3);
+ GEN_CHECK_OFF(DMAR, StatMmioWriteRZ);
+ GEN_CHECK_OFF(DMAR, StatMsiRemapCfiR3);
+ GEN_CHECK_OFF(DMAR, StatMsiRemapCfiRZ);
+ GEN_CHECK_OFF(DMAR, StatMsiRemapRfiR3);
+ GEN_CHECK_OFF(DMAR, StatMsiRemapRfiRZ);
+ GEN_CHECK_OFF(DMAR, StatMemReadR3);
+ GEN_CHECK_OFF(DMAR, StatMemReadRZ);
+ GEN_CHECK_OFF(DMAR, StatMemWriteR3);
+ GEN_CHECK_OFF(DMAR, StatMemWriteRZ);
+ GEN_CHECK_OFF(DMAR, StatMemBulkReadR3);
+ GEN_CHECK_OFF(DMAR, StatMemBulkReadRZ);
+ GEN_CHECK_OFF(DMAR, StatMemBulkWriteR3);
+ GEN_CHECK_OFF(DMAR, StatMemBulkWriteRZ);
+ GEN_CHECK_OFF(DMAR, StatCcInvDsc);
+ GEN_CHECK_OFF(DMAR, StatIotlbInvDsc);
+ GEN_CHECK_OFF(DMAR, StatDevtlbInvDsc);
+ GEN_CHECK_OFF(DMAR, StatIecInvDsc);
+ GEN_CHECK_OFF(DMAR, StatInvWaitDsc);
+ GEN_CHECK_OFF(DMAR, StatPasidIotlbInvDsc);
+ GEN_CHECK_OFF(DMAR, StatPasidCacheInvDsc);
+ GEN_CHECK_OFF(DMAR, StatPasidDevtlbInvDsc);
+# endif
+
+ GEN_CHECK_SIZE(DMARIOPAGE);
+ GEN_CHECK_OFF(DMARIOPAGE, GCPhysBase);
+ GEN_CHECK_OFF(DMARIOPAGE, cShift);
+ GEN_CHECK_OFF(DMARIOPAGE, fPerm);
+
+ GEN_CHECK_SIZE(DMARIOADDRRANGE);
+ GEN_CHECK_OFF(DMARIOADDRRANGE, uAddr);
+ GEN_CHECK_OFF(DMARIOADDRRANGE, cb);
+ GEN_CHECK_OFF(DMARIOADDRRANGE, fPerm);
+
+ GEN_CHECK_SIZE(DMARMEMREQIN);
+ GEN_CHECK_OFF(DMARMEMREQIN, AddrRange);
+ GEN_CHECK_OFF(DMARMEMREQIN, idDevice);
+ GEN_CHECK_OFF(DMARMEMREQIN, Pasid);
+ GEN_CHECK_OFF(DMARMEMREQIN, enmAddrType);
+ GEN_CHECK_OFF(DMARMEMREQIN, enmReqType);
+
+ GEN_CHECK_SIZE(DMARMEMREQOUT);
+ GEN_CHECK_OFF(DMARMEMREQOUT, AddrRange);
+ GEN_CHECK_OFF(DMARMEMREQOUT, idDomain);
+
+ GEN_CHECK_SIZE(DMARMEMREQAUX);
+ GEN_CHECK_OFF(DMARMEMREQAUX, fTtm
+ GEN_CHECK_OFF(DMARMEMREQAUX, fFpd);
+ GEN_CHECK_OFF(DMARMEMREQAUX, cPagingLevel);
+ GEN_CHECK_OFF(DMARMEMREQAUX, GCPhysFlPt);
+ GEN_CHECK_OFF(DMARMEMREQAUX, GCPhysSlPt);
+
+ GEN_CHECK_SIZE(DMARMEMREQREMAP);
+ GEN_CHECK_OFF(DMARMEMREQREMAP, In);
+ GEN_CHECK_OFF(DMARMEMREQREMAP, Aux);
+ GEN_CHECK_OFF(DMARMEMREQREMAP, Out);
+#endif
+
+ return (0);
+}