diff options
Diffstat (limited to 'src/VBox/Devices/testcase/tstDeviceInternal.h')
-rw-r--r-- | src/VBox/Devices/testcase/tstDeviceInternal.h | 578 |
1 files changed, 578 insertions, 0 deletions
diff --git a/src/VBox/Devices/testcase/tstDeviceInternal.h b/src/VBox/Devices/testcase/tstDeviceInternal.h new file mode 100644 index 00000000..b459b90a --- /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-2022 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 */ |