diff options
Diffstat (limited to 'src/VBox/Devices/testcase')
-rw-r--r-- | src/VBox/Devices/testcase/Makefile.kmk | 157 | ||||
-rw-r--r-- | src/VBox/Devices/testcase/tstDevice.cpp | 1043 | ||||
-rw-r--r-- | src/VBox/Devices/testcase/tstDeviceBuiltin.h | 47 | ||||
-rw-r--r-- | src/VBox/Devices/testcase/tstDeviceCfg.cpp | 560 | ||||
-rw-r--r-- | src/VBox/Devices/testcase/tstDeviceCfg.h | 169 | ||||
-rw-r--r-- | src/VBox/Devices/testcase/tstDeviceInternal.h | 578 | ||||
-rw-r--r-- | src/VBox/Devices/testcase/tstDeviceIoFuzz.cpp | 269 | ||||
-rw-r--r-- | src/VBox/Devices/testcase/tstDevicePdmDevHlp.cpp | 6196 | ||||
-rw-r--r-- | src/VBox/Devices/testcase/tstDevicePdmDevHlpR0.cpp | 1523 | ||||
-rw-r--r-- | src/VBox/Devices/testcase/tstDevicePdmThread.cpp | 996 | ||||
-rw-r--r-- | src/VBox/Devices/testcase/tstDevicePlugin.h | 100 | ||||
-rw-r--r-- | src/VBox/Devices/testcase/tstDeviceR0.cpp | 163 | ||||
-rw-r--r-- | src/VBox/Devices/testcase/tstDeviceSsmFuzz.cpp | 200 | ||||
-rw-r--r-- | src/VBox/Devices/testcase/tstDeviceSsmLoadDbg.cpp | 159 | ||||
-rw-r--r-- | src/VBox/Devices/testcase/tstDeviceStructSize.cpp | 454 | ||||
-rw-r--r-- | src/VBox/Devices/testcase/tstDeviceStructSizeRC.cpp | 2264 |
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); +} |