VirtualKD.cpp revision c05577cf78fa798f48bfad5d32a939f077f9760c
af062818b47340eef15700d2f0211576ba3506eevboxsync/* $Id$ */
af062818b47340eef15700d2f0211576ba3506eevboxsync/** @file
af062818b47340eef15700d2f0211576ba3506eevboxsync * VirtualKD - Device stub/loader for fast Windows kernel-mode debugging.
af062818b47340eef15700d2f0211576ba3506eevboxsync *
af062818b47340eef15700d2f0211576ba3506eevboxsync * Contributed by: Igor Shcherbakov
af062818b47340eef15700d2f0211576ba3506eevboxsync * Heavily modified after the contribution.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/*
af062818b47340eef15700d2f0211576ba3506eevboxsync * Copyright (C) 2010-2014 Oracle Corporation
af062818b47340eef15700d2f0211576ba3506eevboxsync *
af062818b47340eef15700d2f0211576ba3506eevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
af062818b47340eef15700d2f0211576ba3506eevboxsync * available from http://www.virtualbox.org. This file is free software;
af062818b47340eef15700d2f0211576ba3506eevboxsync * you can redistribute it and/or modify it under the terms of the GNU
af062818b47340eef15700d2f0211576ba3506eevboxsync * General Public License (GPL) as published by the Free Software
af062818b47340eef15700d2f0211576ba3506eevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
af062818b47340eef15700d2f0211576ba3506eevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
af062818b47340eef15700d2f0211576ba3506eevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsync
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync/*******************************************************************************
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync* Header Files *
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync*******************************************************************************/
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync#define LOG_GROUP LOG_GROUP_DEV_VIRTUALKD
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync#include <VBox/vmm/pdmdev.h>
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync#include <iprt/assert.h>
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync#include <iprt/path.h>
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync#include "VBoxDD.h"
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/*******************************************************************************
af062818b47340eef15700d2f0211576ba3506eevboxsync* Defined Constants And Macros *
af062818b47340eef15700d2f0211576ba3506eevboxsync*******************************************************************************/
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync#define IKDClient_InterfaceVersion 2
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/*******************************************************************************
af062818b47340eef15700d2f0211576ba3506eevboxsync* Structures and Typedefs *
af062818b47340eef15700d2f0211576ba3506eevboxsync*******************************************************************************/
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsynctypedef struct VKDREQUESTHDR
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync unsigned cbData;
af062818b47340eef15700d2f0211576ba3506eevboxsync unsigned cbReplyMax;
af062818b47340eef15700d2f0211576ba3506eevboxsync} VKDREQUESTHDR;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsynctypedef struct VKDREPLYHDR
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync unsigned cbData;
af062818b47340eef15700d2f0211576ba3506eevboxsync char chOne;
af062818b47340eef15700d2f0211576ba3506eevboxsync char chSpace;
af062818b47340eef15700d2f0211576ba3506eevboxsync} VKDREPLYHDR;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsyncclass IKDClient
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsyncpublic:
af062818b47340eef15700d2f0211576ba3506eevboxsync virtual unsigned OnRequest(const char *pRequest, unsigned RequestSize, char **ppReply)=0;
af062818b47340eef15700d2f0211576ba3506eevboxsync virtual unsigned GetRPCCommandHeaderSize()=0;
af062818b47340eef15700d2f0211576ba3506eevboxsync virtual ~IKDClient() {}
af062818b47340eef15700d2f0211576ba3506eevboxsync};
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsynctypedef IKDClient *(*PFNCreateVBoxKDClientEx)(unsigned version);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsynctypedef struct VIRTUALKD
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync bool fOpenChannelDetected;
af062818b47340eef15700d2f0211576ba3506eevboxsync bool fChannelDetectSuccessful;
af062818b47340eef15700d2f0211576ba3506eevboxsync RTLDRMOD hLib;
af062818b47340eef15700d2f0211576ba3506eevboxsync IKDClient *pKDClient;
af062818b47340eef15700d2f0211576ba3506eevboxsync unsigned cbRPCCommandHeaderSize;
af062818b47340eef15700d2f0211576ba3506eevboxsync char abCmdBody[262144];
af062818b47340eef15700d2f0211576ba3506eevboxsync} VIRTUALKD;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/*******************************************************************************
af062818b47340eef15700d2f0211576ba3506eevboxsync* Internal Functions *
af062818b47340eef15700d2f0211576ba3506eevboxsync*******************************************************************************/
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) vkdPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync VIRTUALKD *pThis = PDMINS_2_DATA(pDevIns, VIRTUALKD *);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pThis->fOpenChannelDetected)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync *pu32 = RT_MAKE_U32_FROM_U8('V', 'B', 'O', 'X'); /* 'XOBV', checked in VMWRPC.H */
af062818b47340eef15700d2f0211576ba3506eevboxsync pThis->fOpenChannelDetected = false;
af062818b47340eef15700d2f0211576ba3506eevboxsync pThis->fChannelDetectSuccessful = true;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync else
af062818b47340eef15700d2f0211576ba3506eevboxsync *pu32 = -1;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) vkdPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync VIRTUALKD *pThis = PDMINS_2_DATA(pDevIns, VIRTUALKD *);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync if (Port == 0x5659)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync VKDREQUESTHDR RequestHeader;
589fd26cedb2b4ebbed14f2964cad03cc8ebbca2vboxsync int rc = PDMDevHlpPhysRead(pDevIns, (RTGCPHYS)u32, &RequestHeader, sizeof(RequestHeader));
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!RT_SUCCESS(rc) || !RequestHeader.cbData)
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = PDMDevHlpPhysRead(pDevIns, (RTGCPHYS)(u32 + sizeof(RequestHeader)), pThis->abCmdBody, RequestHeader.cbData);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!RT_SUCCESS(rc))
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync char *pReply = NULL;
af062818b47340eef15700d2f0211576ba3506eevboxsync unsigned cbReply;
af062818b47340eef15700d2f0211576ba3506eevboxsync cbReply = pThis->pKDClient->OnRequest(pThis->abCmdBody + pThis->cbRPCCommandHeaderSize,
af062818b47340eef15700d2f0211576ba3506eevboxsync RequestHeader.cbData - pThis->cbRPCCommandHeaderSize,
af062818b47340eef15700d2f0211576ba3506eevboxsync &pReply);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!pReply)
af062818b47340eef15700d2f0211576ba3506eevboxsync cbReply = 0;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync VKDREPLYHDR ReplyHeader;
af062818b47340eef15700d2f0211576ba3506eevboxsync ReplyHeader.cbData = cbReply + 2;
af062818b47340eef15700d2f0211576ba3506eevboxsync ReplyHeader.chOne = '1';
af062818b47340eef15700d2f0211576ba3506eevboxsync ReplyHeader.chSpace = ' ';
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)u32, &ReplyHeader, sizeof(ReplyHeader));
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!RT_SUCCESS(rc))
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync if (cbReply)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = PDMDevHlpPhysWrite(pDevIns, (RTGCPHYS)(u32 + sizeof(ReplyHeader)), pReply, cbReply);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!RT_SUCCESS(rc))
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync else if (Port == 0x5658)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync if (u32 == 0x564D5868)
af062818b47340eef15700d2f0211576ba3506eevboxsync pThis->fOpenChannelDetected = true;
af062818b47340eef15700d2f0211576ba3506eevboxsync else
af062818b47340eef15700d2f0211576ba3506eevboxsync pThis->fOpenChannelDetected = false;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/**
af062818b47340eef15700d2f0211576ba3506eevboxsync * @interface_method_impl{PDMDEVREG,pfnConstruct}
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) vkdConstruct(PPDMDEVINS pDevIns, int iInstance, PCFGMNODE pCfg)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync VIRTUALKD *pThis = PDMINS_2_DATA(pDevIns, VIRTUALKD *);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync pThis->fOpenChannelDetected = false;
af062818b47340eef15700d2f0211576ba3506eevboxsync pThis->fChannelDetectSuccessful = false;
af062818b47340eef15700d2f0211576ba3506eevboxsync pThis->hLib = NIL_RTLDRMOD;
af062818b47340eef15700d2f0211576ba3506eevboxsync pThis->pKDClient = NULL;
af062818b47340eef15700d2f0211576ba3506eevboxsync pThis->cbRPCCommandHeaderSize = 0;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!CFGMR3AreValuesValid(pCfg,
af062818b47340eef15700d2f0211576ba3506eevboxsync "Path\0"))
af062818b47340eef15700d2f0211576ba3506eevboxsync return VERR_PDM_DEVINS_UNKNOWN_CFG_VALUES;
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync /* This device is a bit unusual, after this point it will not fail to be
af062818b47340eef15700d2f0211576ba3506eevboxsync * constructed, but there will be a warning and it will not work. */
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync char szPath[RTPATH_MAX] = "";
af062818b47340eef15700d2f0211576ba3506eevboxsync CFGMR3QueryString(pCfg, "Path", szPath, sizeof(szPath));
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync RTPathAppend(szPath, sizeof(szPath),
af062818b47340eef15700d2f0211576ba3506eevboxsync#if HC_ARCH_BITS == 64
af062818b47340eef15700d2f0211576ba3506eevboxsync "kdclient64.dll"
af062818b47340eef15700d2f0211576ba3506eevboxsync#else
af062818b47340eef15700d2f0211576ba3506eevboxsync "kdclient.dll"
af062818b47340eef15700d2f0211576ba3506eevboxsync#endif
af062818b47340eef15700d2f0211576ba3506eevboxsync );
af062818b47340eef15700d2f0211576ba3506eevboxsync int rc = RTLdrLoad(szPath, &pThis->hLib);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (RT_FAILURE(rc))
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync PDMDevHlpVMSetRuntimeError(pDevIns, 0 /* fFlags */, "VirtualKD_LOAD",
af062818b47340eef15700d2f0211576ba3506eevboxsync N_("Failed to load VirtualKD library '%s'. Fast kernel-mode debugging will not work"), szPath);
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync PFNCreateVBoxKDClientEx pfnInit;
af062818b47340eef15700d2f0211576ba3506eevboxsync rc = RTLdrGetSymbol(pThis->hLib, "CreateVBoxKDClientEx", (void **)&pfnInit);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (RT_FAILURE(rc))
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync RTLdrClose(pThis->hLib);
af062818b47340eef15700d2f0211576ba3506eevboxsync pThis->hLib = NIL_RTLDRMOD;
af062818b47340eef15700d2f0211576ba3506eevboxsync PDMDevHlpVMSetRuntimeError(pDevIns, 0 /* fFlags */, "VirtualKD_SYMBOL",
af062818b47340eef15700d2f0211576ba3506eevboxsync N_("Failed to find entry point for VirtualKD library '%s'. Fast kernel-mode debugging will not work"), szPath);
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync pThis->pKDClient = pfnInit(IKDClient_InterfaceVersion);
af062818b47340eef15700d2f0211576ba3506eevboxsync if (!pThis->pKDClient)
af062818b47340eef15700d2f0211576ba3506eevboxsync {
af062818b47340eef15700d2f0211576ba3506eevboxsync RTLdrClose(pThis->hLib);
af062818b47340eef15700d2f0211576ba3506eevboxsync pThis->hLib = NIL_RTLDRMOD;
af062818b47340eef15700d2f0211576ba3506eevboxsync PDMDevHlpVMSetRuntimeError(pDevIns, 0 /* fFlags */, "VirtualKD_INIT",
af062818b47340eef15700d2f0211576ba3506eevboxsync N_("Failed to initialize VirtualKD library '%s'. Fast kernel-mode debugging will not work"), szPath);
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync }
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync pThis->cbRPCCommandHeaderSize = pThis->pKDClient->GetRPCCommandHeaderSize();
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync PDMDevHlpIOPortRegister(pDevIns, 0x5658, 2, NULL, vkdPortWrite, vkdPortRead, NULL, NULL, "VirtualKD");
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/**
af062818b47340eef15700d2f0211576ba3506eevboxsync * @interface_method_impl{PDMDEVREG,pfnDestruct}
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsyncstatic DECLCALLBACK(int) vkdDestruct(PPDMDEVINS pDevIns)
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync VIRTUALKD *pThis = PDMINS_2_DATA(pDevIns, VIRTUALKD *);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync delete pThis->pKDClient;
af062818b47340eef15700d2f0211576ba3506eevboxsync if (pThis->hLib != NIL_RTLDRMOD)
af062818b47340eef15700d2f0211576ba3506eevboxsync RTLdrClose(pThis->hLib);
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync return VINF_SUCCESS;
af062818b47340eef15700d2f0211576ba3506eevboxsync}
af062818b47340eef15700d2f0211576ba3506eevboxsync
af062818b47340eef15700d2f0211576ba3506eevboxsync/**
af062818b47340eef15700d2f0211576ba3506eevboxsync * The device registration structure.
af062818b47340eef15700d2f0211576ba3506eevboxsync */
af062818b47340eef15700d2f0211576ba3506eevboxsyncconst PDMDEVREG g_DeviceVirtualKD =
af062818b47340eef15700d2f0211576ba3506eevboxsync{
af062818b47340eef15700d2f0211576ba3506eevboxsync /* u32Version */
af062818b47340eef15700d2f0211576ba3506eevboxsync PDM_DEVREG_VERSION,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* szName */
af062818b47340eef15700d2f0211576ba3506eevboxsync "VirtualKD",
af062818b47340eef15700d2f0211576ba3506eevboxsync /* szRCMod */
af062818b47340eef15700d2f0211576ba3506eevboxsync "",
af062818b47340eef15700d2f0211576ba3506eevboxsync /* szR0Mod */
af062818b47340eef15700d2f0211576ba3506eevboxsync "",
af062818b47340eef15700d2f0211576ba3506eevboxsync /* pszDescription */
af062818b47340eef15700d2f0211576ba3506eevboxsync "Provides fast debugging interface when debugging Windows kernel",
af062818b47340eef15700d2f0211576ba3506eevboxsync /* fFlags */
af062818b47340eef15700d2f0211576ba3506eevboxsync PDM_DEVREG_FLAGS_DEFAULT_BITS,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* fClass */
af062818b47340eef15700d2f0211576ba3506eevboxsync PDM_DEVREG_CLASS_MISC,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* cMaxInstances */
af062818b47340eef15700d2f0211576ba3506eevboxsync 1,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* cbInstance */
af062818b47340eef15700d2f0211576ba3506eevboxsync sizeof(VIRTUALKD),
af062818b47340eef15700d2f0211576ba3506eevboxsync /* pfnConstruct */
af062818b47340eef15700d2f0211576ba3506eevboxsync vkdConstruct,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* pfnDestruct */
af062818b47340eef15700d2f0211576ba3506eevboxsync vkdDestruct,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* pfnRelocate */
af062818b47340eef15700d2f0211576ba3506eevboxsync NULL,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* pfnIOCtl */
af062818b47340eef15700d2f0211576ba3506eevboxsync NULL,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* pfnPowerOn */
af062818b47340eef15700d2f0211576ba3506eevboxsync NULL,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* pfnReset */
af062818b47340eef15700d2f0211576ba3506eevboxsync NULL,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* pfnSuspend */
af062818b47340eef15700d2f0211576ba3506eevboxsync NULL,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* pfnResume */
af062818b47340eef15700d2f0211576ba3506eevboxsync NULL,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* pfnAttach */
af062818b47340eef15700d2f0211576ba3506eevboxsync NULL,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* pfnDetach */
af062818b47340eef15700d2f0211576ba3506eevboxsync NULL,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* pfnQueryInterface */
af062818b47340eef15700d2f0211576ba3506eevboxsync NULL,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* pfnInitComplete */
af062818b47340eef15700d2f0211576ba3506eevboxsync NULL,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* pfnPowerOff */
af062818b47340eef15700d2f0211576ba3506eevboxsync NULL,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* pfnSoftReset */
af062818b47340eef15700d2f0211576ba3506eevboxsync NULL,
af062818b47340eef15700d2f0211576ba3506eevboxsync /* u32VersionEnd */
af062818b47340eef15700d2f0211576ba3506eevboxsync PDM_DEVREG_VERSION
af062818b47340eef15700d2f0211576ba3506eevboxsync};
af062818b47340eef15700d2f0211576ba3506eevboxsync