From 215d2c7a4bc9b7d581cda0cc49924f9fa2228df6 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Tue, 31 Oct 2017 22:09:57 +1100 Subject: [PATCH] [host] implemented initial IVSHMEM interface class --- host/ivshmem.cpp | 192 ++++++++++++++++++++++++++ host/ivshmem.h | 42 ++++++ host/kvm-ivshmem-host.vcxproj | 20 ++- host/kvm-ivshmem-host.vcxproj.filters | 10 +- host/{main.c => main.cpp} | 36 +++-- 5 files changed, 280 insertions(+), 20 deletions(-) create mode 100644 host/ivshmem.cpp create mode 100644 host/ivshmem.h rename host/{main.c => main.cpp} (84%) diff --git a/host/ivshmem.cpp b/host/ivshmem.cpp new file mode 100644 index 00000000..387db44b --- /dev/null +++ b/host/ivshmem.cpp @@ -0,0 +1,192 @@ +#include "ivshmem.h" + +#include +#include +#include +#include + +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(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(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(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(map.size ); + m_peerID = static_cast(map.peerID ); + m_vectors = static_cast(map.vectors); + + return m_memory; +} \ No newline at end of file diff --git a/host/ivshmem.h b/host/ivshmem.h new file mode 100644 index 00000000..9aef697a --- /dev/null +++ b/host/ivshmem.h @@ -0,0 +1,42 @@ +#pragma once + +#define W32_LEAN_AND_MEAN +#include +#include + +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; +}; \ No newline at end of file diff --git a/host/kvm-ivshmem-host.vcxproj b/host/kvm-ivshmem-host.vcxproj index 6cfd8d65..7f09f611 100644 --- a/host/kvm-ivshmem-host.vcxproj +++ b/host/kvm-ivshmem-host.vcxproj @@ -69,17 +69,19 @@ true - $(VC_IncludePath);$(WindowsSDK_IncludePath);..\common + $(VC_IncludePath);$(WindowsSDK_IncludePath);..\ true - $(VC_IncludePath);$(WindowsSDK_IncludePath);..\common + $(VC_IncludePath);$(WindowsSDK_IncludePath);..\ false + $(VC_IncludePath);$(WindowsSDK_IncludePath);..\ false + $(VC_IncludePath);$(WindowsSDK_IncludePath);..\ @@ -87,12 +89,13 @@ Level3 Disabled - WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions) + WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions);DEBUG true Console true + 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) @@ -101,12 +104,13 @@ Level3 Disabled - _DEBUG;_WINDOWS;%(PreprocessorDefinitions) + _DEBUG;_WINDOWS;%(PreprocessorDefinitions);DEBUG true Console true + 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) @@ -125,6 +129,7 @@ true true true + 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) @@ -143,10 +148,15 @@ true true true + 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) - + + + + + diff --git a/host/kvm-ivshmem-host.vcxproj.filters b/host/kvm-ivshmem-host.vcxproj.filters index 6827613a..77e02d12 100644 --- a/host/kvm-ivshmem-host.vcxproj.filters +++ b/host/kvm-ivshmem-host.vcxproj.filters @@ -15,8 +15,16 @@ - + + Source Files + + Source Files + + + Header Files + + \ No newline at end of file diff --git a/host/main.c b/host/main.cpp similarity index 84% rename from host/main.c rename to host/main.cpp index 17e8fea5..00ce20c7 100644 --- a/host/main.c +++ b/host/main.cpp @@ -1,12 +1,11 @@ #include #include +#include + +#include "ivshmem.h" #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 @@ -18,9 +17,9 @@ struct App struct App app = { - .serviceStatus = {0}, - .statusHandle = NULL, - .serviceStopEvent = INVALID_HANDLE_VALUE + {0}, + NULL, + INVALID_HANDLE_VALUE }; //============================================================================= @@ -35,7 +34,7 @@ int main(int argc, TCHAR *argv[]) { SERVICE_TABLE_ENTRY ServiceTable[] = { - {SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain}, + {_T(SERVICE_NAME), (LPSERVICE_MAIN_FUNCTION)ServiceMain}, {NULL, NULL} }; @@ -59,7 +58,7 @@ int main(int argc, TCHAR *argv[]) VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv) { - app.statusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler); + app.statusHandle = RegisterServiceCtrlHandler(_T(SERVICE_NAME), ServiceCtrlHandler); if (!app.statusHandle) return; @@ -73,7 +72,7 @@ VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv) if (SetServiceStatus(app.statusHandle, &app.serviceStatus) == FALSE) { - OutputDebugString(DEBUG_HERE("SetServiceStatus failed")); + DEBUG_ERROR("SetServiceStatus failed"); return; } @@ -86,7 +85,7 @@ VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv) app.serviceStatus.dwCheckPoint = 1; if (SetServiceStatus(app.statusHandle, &app.serviceStatus) == FALSE) { - OutputDebugString(DEBUG_HERE("SetServiceStatus failed")); + DEBUG_ERROR("SetServiceStatus failed"); return; } } @@ -97,7 +96,7 @@ VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv) app.serviceStatus.dwCheckPoint = 0; if (SetServiceStatus(app.statusHandle, &app.serviceStatus) == FALSE) { - OutputDebugString(DEBUG_HERE("SetServiceStatus failed")); + DEBUG_ERROR("SetServiceStatus failed"); return; } @@ -112,7 +111,7 @@ VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv) if (SetServiceStatus(app.statusHandle, &app.serviceStatus) == FALSE) { - OutputDebugString(DEBUG_HERE("SetServiceStatus failed")); + DEBUG_ERROR("SetServiceStatus failed"); return; } } @@ -133,7 +132,7 @@ VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode) app.serviceStatus.dwCheckPoint = 4; if (SetServiceStatus(app.statusHandle, &app.serviceStatus) == FALSE) - OutputDebugString(DEBUG_HERE("SetServiceStatus failed")); + DEBUG_ERROR("SetServiceStatus failed"); SetEvent(app.serviceStopEvent); break; @@ -147,10 +146,19 @@ VOID WINAPI ServiceCtrlHandler(DWORD CtrlCode) 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) { Sleep(1000); } + + ivshmem->DeInitialize(); return ERROR_SUCCESS; }