Correct detection of compatible adapters

compare current library path with driver store path

Resolves: NEO-4457
Change-Id: Ibf5463d6f51595fbb45ad9b23d6f2cfcceb907bf
Signed-off-by: Mateusz Jablonski <mateusz.jablonski@intel.com>
This commit is contained in:
Mateusz Jablonski 2020-03-17 11:55:53 +01:00 committed by sys_ocldev
parent 1ce4f56c9f
commit e46142be4d
6 changed files with 143 additions and 104 deletions

View File

@ -28,6 +28,10 @@
namespace NEO {
namespace SysCalls {
extern const wchar_t *currentLibraryPath;
}
extern CommandStreamReceiverCreateFunc commandStreamReceiverFactory[IGFX_MAX_CORE];
CommandStreamReceiver *createMockCommandStreamReceiver(bool withAubDump, ExecutionEnvironment &executionEnvironment, uint32_t rootDeviceIndex);
@ -99,44 +103,58 @@ TEST_F(DriverInfoDeviceTest, GivenDeviceCreatedWithoutCorrectOSInterfaceThenDont
EXPECT_EQ(nullptr, device->driverInfo.get());
}
class RegistryReaderMock : public SettingsReader {
class MockRegistryReader : public SettingsReader {
public:
std::string nameString;
std::string versionString;
std::string getSetting(const char *settingName, const std::string &value) {
std::string getSetting(const char *settingName, const std::string &value) override {
std::string key(settingName);
if (key == "HardwareInformation.AdapterString") {
properNameKey = true;
} else if (key == "DriverVersion") {
properVersionKey = true;
}
if (key == "DriverStorePathForComputeRuntime") {
return driverStorePath;
}
return value;
}
bool getSetting(const char *settingName, bool defaultValue) { return defaultValue; };
int32_t getSetting(const char *settingName, int32_t defaultValue) { return defaultValue; };
const char *appSpecificLocation(const std::string &name) { return name.c_str(); };
bool getSetting(const char *settingName, bool defaultValue) override { return defaultValue; };
int32_t getSetting(const char *settingName, int32_t defaultValue) override { return defaultValue; };
const char *appSpecificLocation(const std::string &name) override { return name.c_str(); };
bool properNameKey = false;
bool properVersionKey = false;
std::string driverStorePath = "driverStore\\0x8086";
};
TEST(DriverInfo, GivenDriverInfoWhenThenReturnNonNullptr) {
MockDriverInfoWindows driverInfo("");
RegistryReaderMock *registryReaderMock = new RegistryReaderMock();
struct DriverInfoWindowsTest : public ::testing::Test {
driverInfo.registryReader.reset(registryReaderMock);
void SetUp() override {
DriverInfoWindows::createRegistryReaderFunc = [](const std::string &) -> std::unique_ptr<SettingsReader> {
return std::make_unique<MockRegistryReader>();
};
driverInfo = std::make_unique<MockDriverInfoWindows>("");
}
VariableBackup<decltype(DriverInfoWindows::createRegistryReaderFunc)> createFuncBackup{&DriverInfoWindows::createRegistryReaderFunc};
std::unique_ptr<MockDriverInfoWindows> driverInfo;
};
TEST_F(DriverInfoWindowsTest, GivenDriverInfoWhenThenReturnNonNullptr) {
auto registryReaderMock = static_cast<MockRegistryReader *>(driverInfo->registryReader.get());
std::string defaultName = "defaultName";
auto name = driverInfo.getDeviceName(defaultName);
auto name = driverInfo->getDeviceName(defaultName);
EXPECT_STREQ(defaultName.c_str(), name.c_str());
EXPECT_TRUE(registryReaderMock->properNameKey);
std::string defaultVersion = "defaultVersion";
auto driverVersion = driverInfo.getVersion(defaultVersion);
auto driverVersion = driverInfo->getVersion(defaultVersion);
EXPECT_STREQ(defaultVersion.c_str(), driverVersion.c_str());
EXPECT_TRUE(registryReaderMock->properVersionKey);
@ -176,9 +194,21 @@ TEST(DriverInfo, givenNotInitializedOsInterfaceWhenCreateDriverInfoThenReturnDri
TEST(DriverInfo, givenInitializedOsInterfaceWhenCreateDriverInfoWindowsThenSetRegistryReaderWithExpectRegKey) {
std::string path = "";
std::unique_ptr<MockDriverInfoWindows> driverInfo(MockDriverInfoWindows::create(path));
std::unique_ptr<TestedRegistryReader> reader(new TestedRegistryReader(path));
EXPECT_NE(nullptr, reader);
EXPECT_STREQ(driverInfo->getRegistryReaderRegKey(), reader->getRegKey());
EXPECT_STREQ(driverInfo->getRegistryReaderRegKey(), driverInfo->reader->getRegKey());
};
TEST_F(DriverInfoWindowsTest, whenCurrentLibraryIsLoadedFromDriverStorePointedByDriverInfoThenItIsCompatible) {
VariableBackup<const wchar_t *> currentLibraryPathBackup(&SysCalls::currentLibraryPath);
currentLibraryPathBackup = L"driverStore\\0x8086\\myLib.dll";
EXPECT_TRUE(driverInfo->isCompatibleDriverStore());
}
TEST_F(DriverInfoWindowsTest, whenCurrentLibraryIsLoadedFromDifferentDriverStoreThanPointedByDriverInfoThenItIsNotCompatible) {
VariableBackup<const wchar_t *> currentLibraryPathBackup(&SysCalls::currentLibraryPath);
currentLibraryPathBackup = L"driverStore\\different_driverStore\\myLib.dll";
EXPECT_FALSE(driverInfo->isCompatibleDriverStore());
}
} // namespace NEO

View File

@ -16,7 +16,7 @@ constexpr uintptr_t dummyHandle = static_cast<uintptr_t>(0x7);
BOOL systemPowerStatusRetVal = 1;
BYTE systemPowerStatusACLineStatusOverride = 1;
HMODULE handleValue = reinterpret_cast<HMODULE>(dummyHandle);
const wchar_t *igdrclFilePath = L"";
const wchar_t *currentLibraryPath = L"";
HANDLE createEvent(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCSTR lpName) {
return reinterpret_cast<HANDLE>(dummyHandle);
@ -42,7 +42,7 @@ DWORD getModuleFileName(HMODULE hModule, LPWSTR lpFilename, DWORD nSize) {
if (hModule != handleValue) {
return FALSE;
}
lstrcpyW(lpFilename, igdrclFilePath);
lstrcpyW(lpFilename, currentLibraryPath);
return TRUE;
}
} // namespace SysCalls

View File

@ -12,9 +12,11 @@
#include "shared/source/helpers/hw_info.h"
#include "shared/source/os_interface/os_library.h"
#include "shared/source/os_interface/os_time.h"
#include "shared/source/os_interface/windows/driver_info_windows.h"
#include "shared/source/os_interface/windows/os_context_win.h"
#include "shared/source/os_interface/windows/os_environment_win.h"
#include "shared/source/os_interface/windows/os_interface.h"
#include "shared/source/os_interface/windows/sys_calls.h"
#include "shared/source/os_interface/windows/wddm/wddm_interface.h"
#include "shared/source/os_interface/windows/wddm_allocation.h"
#include "shared/source/os_interface/windows/wddm_engine_mapper.h"
@ -40,7 +42,7 @@
namespace NEO {
namespace SysCalls {
extern const wchar_t *igdrclFilePath;
extern const wchar_t *currentLibraryPath;
}
extern uint32_t numRootDevicesToEnum;
} // namespace NEO
@ -105,28 +107,6 @@ TEST(WddmDiscoverDevices, WhenNoHwDeviceIdIsProvidedToWddmThenWddmIsNotCreated)
EXPECT_THROW(auto wddm = std::make_unique<MockWddm>(nullptr, rootDeviceEnvironment), std::exception);
}
TEST(WddmDiscoverDevices, WhenAdapterDescriptionContainsDCHDAndgdrclPathDoesntContainDchDThenNoDeviceIsDiscovered) {
VariableBackup<const wchar_t *> descriptionBackup(&UltIDXGIAdapter1::description);
descriptionBackup = L"Intel DCH-D";
VariableBackup<const wchar_t *> igdrclPathBackup(&SysCalls::igdrclFilePath);
igdrclPathBackup = L"intel_dch.inf";
ExecutionEnvironment executionEnvironment;
auto hwDeviceIds = OSInterface::discoverDevices(executionEnvironment);
EXPECT_TRUE(hwDeviceIds.empty());
}
TEST(WddmDiscoverDevices, WhenAdapterDescriptionContainsDCHIAndgdrclPathDoesntContainDchIThenNoDeviceIsDiscovered) {
VariableBackup<const wchar_t *> descriptionBackup(&UltIDXGIAdapter1::description);
descriptionBackup = L"Intel DCH-I";
VariableBackup<const wchar_t *> igdrclPathBackup(&SysCalls::igdrclFilePath);
igdrclPathBackup = L"intel_dch.inf";
ExecutionEnvironment executionEnvironment;
auto hwDeviceIds = OSInterface::discoverDevices(executionEnvironment);
EXPECT_TRUE(hwDeviceIds.empty());
}
TEST(WddmDiscoverDevices, WhenMultipleRootDevicesAreAvailableThenAllAreDiscovered) {
VariableBackup<uint32_t> backup{&numRootDevicesToEnum};
numRootDevicesToEnum = 3u;
@ -135,30 +115,6 @@ TEST(WddmDiscoverDevices, WhenMultipleRootDevicesAreAvailableThenAllAreDiscovere
EXPECT_EQ(numRootDevicesToEnum, hwDeviceIds.size());
}
TEST(WddmDiscoverDevices, WhenAdapterDescriptionContainsDCHDAndgdrclPathContainsDchDThenAdapterIsDiscovered) {
VariableBackup<const wchar_t *> descriptionBackup(&UltIDXGIAdapter1::description);
descriptionBackup = L"Intel DCH-D";
VariableBackup<const wchar_t *> igdrclPathBackup(&SysCalls::igdrclFilePath);
igdrclPathBackup = L"intel_dch_d.inf";
ExecutionEnvironment executionEnvironment;
auto hwDeviceIds = OSInterface::discoverDevices(executionEnvironment);
EXPECT_EQ(1u, hwDeviceIds.size());
EXPECT_NE(nullptr, hwDeviceIds[0].get());
}
TEST(Wddm20EnumAdaptersTest, WhenAdapterDescriptionContainsDCHIAndgdrclPathContainsDchIThenAdapterIsDiscovered) {
VariableBackup<const wchar_t *> descriptionBackup(&UltIDXGIAdapter1::description);
descriptionBackup = L"Intel DCH-I";
VariableBackup<const wchar_t *> igdrclPathBackup(&SysCalls::igdrclFilePath);
igdrclPathBackup = L"intel_dch_i.inf";
ExecutionEnvironment executionEnvironment;
auto hwDeviceIds = OSInterface::discoverDevices(executionEnvironment);
EXPECT_EQ(1u, hwDeviceIds.size());
EXPECT_NE(nullptr, hwDeviceIds[0].get());
}
TEST(WddmDiscoverDevices, WhenAdapterDescriptionContainsVirtualRenderThenAdapterIsDiscovered) {
VariableBackup<const wchar_t *> descriptionBackup(&UltIDXGIAdapter1::description);
descriptionBackup = L"Virtual Render";
@ -1399,3 +1355,32 @@ TEST_F(WddmTest, GivenResidencyLoggingEnabledWhenMakeResidentAndWaitPagingThenEx
EXPECT_FALSE(logger->makeResidentCall);
EXPECT_FALSE(logger->enterWait);
}
TEST(DiscoverDevices, whenDriverInfoHasIncompatibleDriverStoreThenHwDeviceIdIsNotCreated) {
class MockRegistryReader : public SettingsReader {
public:
std::string getSetting(const char *settingName, const std::string &value) override {
std::string key(settingName);
if (key == "DriverStorePathForComputeRuntime") {
return driverStorePath;
}
return value;
}
bool getSetting(const char *settingName, bool defaultValue) override { return defaultValue; };
int32_t getSetting(const char *settingName, int32_t defaultValue) override { return defaultValue; };
const char *appSpecificLocation(const std::string &name) override { return name.c_str(); };
std::string driverStorePath = "driverStore\\0x8086";
};
VariableBackup<decltype(DriverInfoWindows::createRegistryReaderFunc)> createFuncBackup{&DriverInfoWindows::createRegistryReaderFunc};
DriverInfoWindows::createRegistryReaderFunc = [](const std::string &) -> std::unique_ptr<SettingsReader> {
return std::make_unique<MockRegistryReader>();
};
VariableBackup<const wchar_t *> currentLibraryPathBackup(&SysCalls::currentLibraryPath);
currentLibraryPathBackup = L"driverStore\\different_driverStore\\myLib.dll";
ExecutionEnvironment executionEnvironment;
auto hwDeviceIds = OSInterface::discoverDevices(executionEnvironment);
EXPECT_TRUE(hwDeviceIds.empty());
}

View File

@ -9,8 +9,29 @@
#include "shared/source/os_interface/windows/debug_registry_reader.h"
#include "shared/source/os_interface/windows/os_interface.h"
#include "shared/source/os_interface/windows/sys_calls.h"
#include "shared/source/os_interface/windows/wddm/wddm.h"
std::string getCurrentLibraryPath() {
std::string returnValue;
WCHAR pathW[MAX_PATH];
char path[MAX_PATH];
HMODULE handle = NULL;
auto status = NEO::SysCalls::getModuleHandle(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
reinterpret_cast<LPCWSTR>(&getCurrentLibraryPath), &handle);
if (status != 0) {
status = NEO::SysCalls::getModuleFileName(handle, pathW, sizeof(pathW));
if (status != 0) {
std::wcstombs(path, pathW, MAX_PATH);
returnValue.append(path);
}
}
return returnValue;
}
namespace NEO {
DriverInfo *DriverInfo::create(OSInterface *osInterface) {
@ -26,7 +47,7 @@ DriverInfo *DriverInfo::create(OSInterface *osInterface) {
};
DriverInfoWindows::DriverInfoWindows(std::string &&fullPath) : path(DriverInfoWindows::trimRegistryKey(fullPath)),
registryReader(std::make_unique<RegistryReader>(false, path)) {}
registryReader(createRegistryReaderFunc(path)) {}
std::string DriverInfoWindows::trimRegistryKey(std::string path) {
std::string prefix("\\REGISTRY\\MACHINE\\");
@ -44,4 +65,14 @@ std::string DriverInfoWindows::getDeviceName(std::string defaultName) {
std::string DriverInfoWindows::getVersion(std::string defaultVersion) {
return registryReader.get()->getSetting("DriverVersion", defaultVersion);
};
bool DriverInfoWindows::isCompatibleDriverStore() const {
auto currentLibraryPath = getCurrentLibraryPath();
auto driverStorePath = registryReader.get()->getSetting("DriverStorePathForComputeRuntime", currentLibraryPath);
return currentLibraryPath.find(driverStorePath.c_str()) == 0u;
}
decltype(DriverInfoWindows::createRegistryReaderFunc) DriverInfoWindows::createRegistryReaderFunc = [](const std::string &registryPath) -> std::unique_ptr<SettingsReader> {
return std::make_unique<RegistryReader>(false, registryPath);
};
} // namespace NEO

View File

@ -9,6 +9,7 @@
#include "shared/source/os_interface/driver_info.h"
#include <functional>
#include <memory>
#include <string>
@ -19,8 +20,11 @@ class SettingsReader;
class DriverInfoWindows : public DriverInfo {
public:
DriverInfoWindows(std::string &&path);
std::string getDeviceName(std::string defaultName);
std::string getVersion(std::string defaultVersion);
std::string getDeviceName(std::string defaultName) override;
std::string getVersion(std::string defaultVersion) override;
bool isCompatibleDriverStore() const;
static std::function<std::unique_ptr<SettingsReader>(const std::string &registryPath)> createRegistryReaderFunc;
protected:
static std::string trimRegistryKey(std::string key);

View File

@ -17,12 +17,12 @@
#include "shared/source/helpers/windows/gmm_callbacks.h"
#include "shared/source/os_interface/hw_info_config.h"
#include "shared/source/os_interface/windows/debug_registry_reader.h"
#include "shared/source/os_interface/windows/driver_info_windows.h"
#include "shared/source/os_interface/windows/gdi_interface.h"
#include "shared/source/os_interface/windows/kmdaf_listener.h"
#include "shared/source/os_interface/windows/os_context_win.h"
#include "shared/source/os_interface/windows/os_environment_win.h"
#include "shared/source/os_interface/windows/os_interface.h"
#include "shared/source/os_interface/windows/sys_calls.h"
#include "shared/source/os_interface/windows/wddm/wddm_interface.h"
#include "shared/source/os_interface/windows/wddm/wddm_residency_logger.h"
#include "shared/source/os_interface/windows/wddm_allocation.h"
@ -35,24 +35,6 @@
#include <dxgi.h>
std::wstring getIgdrclPath() {
std::wstring returnValue;
WCHAR path[255];
HMODULE handle = NULL;
auto status = NEO::SysCalls::getModuleHandle(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
reinterpret_cast<LPCWSTR>(&getIgdrclPath), &handle);
if (status != 0) {
status = NEO::SysCalls::getModuleFileName(handle, path, sizeof(path));
if (status != 0) {
returnValue.append(path);
}
}
return returnValue;
}
namespace NEO {
extern Wddm::CreateDXGIFactoryFcn getCreateDxgiFactory();
extern Wddm::GetSystemInfoFcn getGetSystemInfo();
@ -233,10 +215,32 @@ std::unique_ptr<HwDeviceId> createHwDeviceIdFromAdapterLuid(OsEnvironmentWin &os
OpenAdapterData.AdapterLuid = adapterLuid;
auto status = osEnvironment.gdi->openAdapterFromLuid(&OpenAdapterData);
if (status == STATUS_SUCCESS) {
return std::make_unique<HwDeviceId>(OpenAdapterData.hAdapter, adapterLuid, &osEnvironment);
if (status != STATUS_SUCCESS) {
DEBUG_BREAK_IF("openAdapterFromLuid failed");
return nullptr;
}
return nullptr;
D3DKMT_QUERYADAPTERINFO QueryAdapterInfo = {0};
ADAPTER_INFO adapterInfo = {0};
QueryAdapterInfo.hAdapter = OpenAdapterData.hAdapter;
QueryAdapterInfo.Type = KMTQAITYPE_UMDRIVERPRIVATE;
QueryAdapterInfo.pPrivateDriverData = &adapterInfo;
QueryAdapterInfo.PrivateDriverDataSize = sizeof(ADAPTER_INFO);
status = osEnvironment.gdi->queryAdapterInfo(&QueryAdapterInfo);
if (status != STATUS_SUCCESS) {
DEBUG_BREAK_IF("queryAdapterInfo failed");
return nullptr;
}
std::string deviceRegistryPath = adapterInfo.DeviceRegistryPath;
DriverInfoWindows driverInfo(std::move(deviceRegistryPath));
if (!driverInfo.isCompatibleDriverStore()) {
return nullptr;
}
return std::make_unique<HwDeviceId>(OpenAdapterData.hAdapter, adapterLuid, &osEnvironment);
}
std::vector<std::unique_ptr<HwDeviceId>> OSInterface::discoverDevices(ExecutionEnvironment &executionEnvironment) {
@ -256,8 +260,6 @@ std::vector<std::unique_ptr<HwDeviceId>> OSInterface::discoverDevices(ExecutionE
IDXGIAdapter1 *pAdapter = nullptr;
DWORD iDevNum = 0;
auto igdrclPath = getIgdrclPath();
HRESULT hr = Wddm::createDxgiFactory(__uuidof(IDXGIFactory), (void **)(&pFactory));
if ((hr != S_OK) || (pFactory == nullptr)) {
return hwDeviceIds;
@ -274,20 +276,7 @@ std::vector<std::unique_ptr<HwDeviceId>> OSInterface::discoverDevices(ExecutionE
(wcsstr(OpenAdapterDesc.Description, L"Virtual Render") != 0)) {
char deviceId[16];
sprintf_s(deviceId, "%X", OpenAdapterDesc.DeviceId);
bool choosenDevice = (DebugManager.flags.ForceDeviceId.get() == "unk") || (DebugManager.flags.ForceDeviceId.get() == deviceId);
if (choosenDevice) {
if (wcsstr(OpenAdapterDesc.Description, L"DCH-D") != 0) {
if (wcsstr(igdrclPath.c_str(), L"_dch_d.inf") != 0) {
createHwDeviceId = true;
}
} else if (wcsstr(OpenAdapterDesc.Description, L"DCH-I") != 0) {
if (wcsstr(igdrclPath.c_str(), L"_dch_i.inf") != 0) {
createHwDeviceId = true;
}
} else {
createHwDeviceId = true;
}
}
createHwDeviceId = (DebugManager.flags.ForceDeviceId.get() == "unk") || (DebugManager.flags.ForceDeviceId.get() == deviceId);
}
if (createHwDeviceId) {
auto hwDeviceId = createHwDeviceIdFromAdapterLuid(*osEnvironment, OpenAdapterDesc.AdapterLuid);