[host] implemented initial IVSHMEM interface class

This commit is contained in:
Geoffrey McRae 2017-10-31 22:09:57 +11:00
parent f24cf74238
commit 215d2c7a4b
5 changed files with 280 additions and 20 deletions

192
host/ivshmem.cpp Normal file
View File

@ -0,0 +1,192 @@
#include "ivshmem.h"
#include <Windows.h>
#include <SetupAPI.h>
#include <vendor\kvm-guest-drivers-windows\ivshmem\Public.h>
#include <common\debug.h>
IVSHMEM * IVSHMEM::m_instance = NULL;
IVSHMEM::IVSHMEM() :
m_initialized(false),
m_handle(INVALID_HANDLE_VALUE),
m_gotSize(false),
m_gotPeerID(false),
m_gotMemory(false)
{
}
IVSHMEM::~IVSHMEM()
{
DeInitialize();
}
bool IVSHMEM::Initialize()
{
if (m_initialized)
DeInitialize();
HDEVINFO deviceInfoSet;
PSP_DEVICE_INTERFACE_DETAIL_DATA infData = NULL;
SP_DEVICE_INTERFACE_DATA deviceInterfaceData;
deviceInfoSet = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE);
ZeroMemory(&deviceInterfaceData, sizeof(SP_DEVICE_INTERFACE_DATA));
deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
while (true)
{
if (SetupDiEnumDeviceInterfaces(deviceInfoSet, NULL, &GUID_DEVINTERFACE_IVSHMEM, 0, &deviceInterfaceData) == FALSE)
{
DWORD error = GetLastError();
if (error == ERROR_NO_MORE_ITEMS)
{
DEBUG_ERROR("Unable to enumerate the device, is it attached?");
break;
}
DEBUG_ERROR("SetupDiEnumDeviceInterfaces failed");
break;
}
DWORD reqSize = 0;
SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, NULL, 0, &reqSize, NULL);
if (!reqSize)
{
DEBUG_ERROR("SetupDiGetDeviceInterfaceDetail");
break;
}
infData = static_cast<PSP_DEVICE_INTERFACE_DETAIL_DATA>(malloc(reqSize));
ZeroMemory(infData, reqSize);
infData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
if (!SetupDiGetDeviceInterfaceDetail(deviceInfoSet, &deviceInterfaceData, infData, reqSize, NULL, NULL))
{
DEBUG_ERROR("SetupDiGetDeviceInterfaceDetail");
break;
}
m_handle = CreateFile(infData->DevicePath, 0, 0, NULL, OPEN_EXISTING, 0, 0);
if (m_handle == INVALID_HANDLE_VALUE)
{
DEBUG_ERROR("CreateFile returned INVALID_HANDLE_VALUE");
break;
}
m_initialized = true;
break;
}
if (infData)
free(infData);
SetupDiDestroyDeviceInfoList(deviceInfoSet);
return m_initialized;
}
void IVSHMEM::DeInitialize()
{
if (!m_initialized)
return;
if (m_gotMemory)
{
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_RELEASE_MMAP, NULL, 0, NULL, 0, NULL, NULL))
DEBUG_ERROR("DeviceIoControl failed: %d", GetLastError());
m_memory = NULL;
}
if (m_handle != INVALID_HANDLE_VALUE)
CloseHandle(m_handle);
m_initialized = false;
m_handle = INVALID_HANDLE_VALUE;
m_gotSize = false;
m_gotPeerID = false;
m_gotVectors = false;
m_gotMemory = false;
}
bool IVSHMEM::IsInitialized()
{
return m_initialized;
}
UINT64 IVSHMEM::GetSize()
{
if (!m_initialized)
return 0;
if (m_gotSize)
return m_size;
IVSHMEM_SIZE size;
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REQUEST_SIZE, NULL, 0, &size, sizeof(IVSHMEM_SIZE), NULL, NULL))
{
DEBUG_ERROR("DeviceIoControl Failed: %d", GetLastError());
return 0;
}
m_gotSize = true;
m_size = static_cast<UINT64>(size);
return m_size;
}
UINT16 IVSHMEM::GetPeerID()
{
if (!m_initialized)
return 0;
if (m_gotPeerID)
return m_peerID;
IVSHMEM_PEERID peerID;
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REQUEST_SIZE, NULL, 0, &peerID, sizeof(IVSHMEM_PEERID), NULL, NULL))
{
DEBUG_ERROR("DeviceIoControl Failed: %d", GetLastError());
return 0;
}
m_gotPeerID = true;
m_peerID = static_cast<UINT16>(peerID);
return m_peerID;
}
UINT16 IVSHMEM::GetVectors()
{
if (!m_initialized)
return 0;
if (!m_gotVectors)
return 0;
return m_vectors;
}
void * IVSHMEM::GetMemory()
{
if (!m_initialized)
return NULL;
if (m_gotMemory)
return m_memory;
IVSHMEM_MMAP map;
ZeroMemory(&map, sizeof(IVSHMEM_MMAP));
if (!DeviceIoControl(m_handle, IOCTL_IVSHMEM_REQUEST_MMAP, NULL, 0, &map, sizeof(IVSHMEM_MMAP), NULL, NULL))
{
DEBUG_ERROR("DeviceIoControl Failed: %d", GetLastError());
return NULL;
}
m_gotSize = true;
m_gotPeerID = true;
m_gotMemory = true;
m_gotVectors = true;
m_size = static_cast<UINT64>(map.size );
m_peerID = static_cast<UINT16>(map.peerID );
m_vectors = static_cast<UINT16>(map.vectors);
return m_memory;
}

42
host/ivshmem.h Normal file
View File

@ -0,0 +1,42 @@
#pragma once
#define W32_LEAN_AND_MEAN
#include <Windows.h>
#include <stdbool.h>
class IVSHMEM
{
public:
static IVSHMEM * Get()
{
if (!m_instance)
m_instance = new IVSHMEM();
return m_instance;
}
bool Initialize();
void DeInitialize();
bool IsInitialized();
UINT64 GetSize();
UINT16 GetPeerID();
UINT16 GetVectors();
void * GetMemory();
protected:
private:
static IVSHMEM * m_instance;
IVSHMEM();
~IVSHMEM();
bool m_initialized;
HANDLE m_handle;
UINT64 m_size ; bool m_gotSize ;
UINT16 m_peerID ; bool m_gotPeerID;
void * m_memory ; bool m_gotMemory;
UINT16 m_vectors; bool m_gotVectors;
};

View File

@ -69,17 +69,19 @@
<PropertyGroup Label="UserMacros" /> <PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\common</IncludePath> <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\</IncludePath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental> <LinkIncremental>true</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\common</IncludePath> <IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\</IncludePath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\</IncludePath>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental> <LinkIncremental>false</LinkIncremental>
<IncludePath>$(VC_IncludePath);$(WindowsSDK_IncludePath);..\</IncludePath>
</PropertyGroup> </PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile> <ClCompile>
@ -87,12 +89,13 @@
</PrecompiledHeader> </PrecompiledHeader>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);DEBUG</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
@ -101,12 +104,13 @@
</PrecompiledHeader> </PrecompiledHeader>
<WarningLevel>Level3</WarningLevel> <WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization> <Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessorDefinitions>_DEBUG;_WINDOWS;%(PreprocessorDefinitions);DEBUG</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck> <SDLCheck>true</SDLCheck>
</ClCompile> </ClCompile>
<Link> <Link>
<SubSystem>Console</SubSystem> <SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
@ -125,6 +129,7 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
@ -143,10 +148,15 @@
<EnableCOMDATFolding>true</EnableCOMDATFolding> <EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences> <OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;setupapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="main.c" /> <ClCompile Include="ivshmem.cpp" />
<ClCompile Include="main.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ivshmem.h" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets"> <ImportGroup Label="ExtensionTargets">

View File

@ -15,8 +15,16 @@
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="main.c"> <ClCompile Include="ivshmem.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup>
<ClInclude Include="ivshmem.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project> </Project>

View File

@ -1,12 +1,11 @@
#include <Windows.h> #include <Windows.h>
#include <tchar.h> #include <tchar.h>
#include <common\debug.h>
#include "ivshmem.h"
#define SERVICE_NAME "kvm-ivshmem-host" #define SERVICE_NAME "kvm-ivshmem-host"
#define STR_HELPER(x) #x
#define STR(x) STR_HELPER(x)
#define DEBUG_HERE(...) SERVICE_NAME " " __FUNCTION__ ":" STR(__LINE__) " " ## __VA_ARGS__
//============================================================================= //=============================================================================
struct App struct App
@ -18,9 +17,9 @@ struct App
struct App app = struct App app =
{ {
.serviceStatus = {0}, {0},
.statusHandle = NULL, NULL,
.serviceStopEvent = INVALID_HANDLE_VALUE INVALID_HANDLE_VALUE
}; };
//============================================================================= //=============================================================================
@ -35,7 +34,7 @@ int main(int argc, TCHAR *argv[])
{ {
SERVICE_TABLE_ENTRY ServiceTable[] = SERVICE_TABLE_ENTRY ServiceTable[] =
{ {
{SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain}, {_T(SERVICE_NAME), (LPSERVICE_MAIN_FUNCTION)ServiceMain},
{NULL, NULL} {NULL, NULL}
}; };
@ -59,7 +58,7 @@ int main(int argc, TCHAR *argv[])
VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv) VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{ {
app.statusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler); app.statusHandle = RegisterServiceCtrlHandler(_T(SERVICE_NAME), ServiceCtrlHandler);
if (!app.statusHandle) if (!app.statusHandle)
return; return;
@ -73,7 +72,7 @@ VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
if (SetServiceStatus(app.statusHandle, &app.serviceStatus) == FALSE) if (SetServiceStatus(app.statusHandle, &app.serviceStatus) == FALSE)
{ {
OutputDebugString(DEBUG_HERE("SetServiceStatus failed")); DEBUG_ERROR("SetServiceStatus failed");
return; return;
} }
@ -86,7 +85,7 @@ VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
app.serviceStatus.dwCheckPoint = 1; app.serviceStatus.dwCheckPoint = 1;
if (SetServiceStatus(app.statusHandle, &app.serviceStatus) == FALSE) if (SetServiceStatus(app.statusHandle, &app.serviceStatus) == FALSE)
{ {
OutputDebugString(DEBUG_HERE("SetServiceStatus failed")); DEBUG_ERROR("SetServiceStatus failed");
return; return;
} }
} }
@ -97,7 +96,7 @@ VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
app.serviceStatus.dwCheckPoint = 0; app.serviceStatus.dwCheckPoint = 0;
if (SetServiceStatus(app.statusHandle, &app.serviceStatus) == FALSE) if (SetServiceStatus(app.statusHandle, &app.serviceStatus) == FALSE)
{ {
OutputDebugString(DEBUG_HERE("SetServiceStatus failed")); DEBUG_ERROR("SetServiceStatus failed");
return; return;
} }
@ -112,7 +111,7 @@ VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
if (SetServiceStatus(app.statusHandle, &app.serviceStatus) == FALSE) if (SetServiceStatus(app.statusHandle, &app.serviceStatus) == FALSE)
{ {
OutputDebugString(DEBUG_HERE("SetServiceStatus failed")); DEBUG_ERROR("SetServiceStatus failed");
return; return;
} }
} }
@ -133,7 +132,7 @@ VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode)
app.serviceStatus.dwCheckPoint = 4; app.serviceStatus.dwCheckPoint = 4;
if (SetServiceStatus(app.statusHandle, &app.serviceStatus) == FALSE) if (SetServiceStatus(app.statusHandle, &app.serviceStatus) == FALSE)
OutputDebugString(DEBUG_HERE("SetServiceStatus failed")); DEBUG_ERROR("SetServiceStatus failed");
SetEvent(app.serviceStopEvent); SetEvent(app.serviceStopEvent);
break; break;
@ -147,10 +146,19 @@ VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode)
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam) DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
{ {
IVSHMEM * ivshmem = IVSHMEM::Get();
if (!ivshmem->Initialize())
{
DEBUG_ERROR("Failed to initialize IVSHMEM");
return ERROR;
}
while (WaitForSingleObject(app.serviceStopEvent, 0) != WAIT_OBJECT_0) while (WaitForSingleObject(app.serviceStopEvent, 0) != WAIT_OBJECT_0)
{ {
Sleep(1000); Sleep(1000);
} }
ivshmem->DeInitialize();
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }