/* * Copyright (C) 2018-2024 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "shared/source/device/device.h" #include "shared/source/direct_submission/direct_submission_controller.h" #include "shared/source/helpers/aligned_memory.h" #include "shared/source/helpers/basic_math.h" #include "shared/source/helpers/gfx_core_helper.h" #include "shared/source/memory_manager/memory_manager.h" #include "shared/source/os_interface/driver_info.h" #include "shared/source/os_interface/linux/allocator_helper.h" #include "shared/source/os_interface/linux/i915.h" #include "shared/source/os_interface/linux/ioctl_helper.h" #include "shared/source/os_interface/linux/sys_calls.h" #include "shared/source/os_interface/os_interface.h" #include "shared/test/common/helpers/custom_event_listener.h" #include "shared/test/common/helpers/debug_manager_state_restore.h" #include "shared/test/common/helpers/default_hw_info.inl" #include "shared/test/common/helpers/gtest_helpers.h" #include "shared/test/common/helpers/ult_hw_config.inl" #include "shared/test/common/helpers/variable_backup.h" #include "shared/test/common/libult/signal_utils.h" #include "shared/test/common/mocks/mock_execution_environment.h" #include "shared/test/common/os_interface/linux/device_command_stream_fixture.h" #include "shared/test/common/test_macros/hw_test.h" #include "opencl/source/command_queue/command_queue.h" #include "opencl/source/platform/platform.h" #include "opencl/test/unit_test/linux/drm_wrap.h" #include "opencl/test/unit_test/linux/mock_os_layer.h" #include "gtest/gtest.h" #include "os_inc.h" #include #include namespace Os { extern const char *dxcoreDllName; } namespace NEO { class OsLibrary; void __attribute__((destructor)) platformsDestructor(); extern const DeviceDescriptor deviceDescriptorTable[]; } // namespace NEO NEO::OsLibrary *setAdapterInfo(const PLATFORM *platform, const GT_SYSTEM_INFO *gtSystemInfo, uint64_t gpuAddressSpace) { return nullptr; } void setupExternalDependencies() {} using namespace NEO; class DrmTestsFixture { public: void setUp() { if (deviceDescriptorTable[0].deviceId == 0) { GTEST_SKIP(); } mockRootDeviceEnvironment = static_cast(mockExecutionEnvironment.rootDeviceEnvironments[0].get()); } void tearDown() { } MockExecutionEnvironment mockExecutionEnvironment; MockRootDeviceEnvironment *mockRootDeviceEnvironment = nullptr; }; typedef Test DrmTests; void initializeTestedDevice() { for (uint32_t i = 0; deviceDescriptorTable[i].deviceId != 0; i++) { if (defaultHwInfo->platform.eProductFamily == deviceDescriptorTable[i].pHwInfo->platform.eProductFamily) { deviceId = deviceDescriptorTable[i].deviceId; break; } } } int openRetVal = 0; std::string lastOpenedPath; int testOpen(const char *fullPath, int, ...) { return openRetVal; }; int openCounter = 1; int openWithCounter(const char *fullPath, int, ...) { if (openCounter > 0) { if (fullPath) { lastOpenedPath = fullPath; } openCounter--; return 1023; // valid file descriptor for ULT } return -1; }; struct DrmSimpleTests : public ::testing::Test { void SetUp() override { if (deviceDescriptorTable[0].deviceId == 0) { GTEST_SKIP(); } } MockExecutionEnvironment mockExecutionEnvironment; }; TEST_F(DrmSimpleTests, GivenTwoOpenableDevicesWhenDiscoverDevicesThenCreateTwoHwDeviceIds) { VariableBackup backupOpenFull(&openFull); openFull = openWithCounter; openCounter = 2; auto hwDeviceIds = OSInterface::discoverDevices(mockExecutionEnvironment); EXPECT_EQ(2u, hwDeviceIds.size()); } TEST_F(DrmSimpleTests, GivenSelectedNotExistingDeviceUsingFilterBdfWhenGetDeviceFdThenFail) { DebugManagerStateRestore stateRestore; debugManager.flags.FilterBdfPath.set("invalid"); VariableBackup backupOpenFull(&openFull); openFull = nullptr; // open shouldn't be called auto hwDeviceIds = OSInterface::discoverDevices(mockExecutionEnvironment); EXPECT_TRUE(hwDeviceIds.empty()); } TEST_F(DrmSimpleTests, GivenSelectedExistingDeviceUsingFilterBdfWhenGetDeviceFdThenReturnFd) { DebugManagerStateRestore stateRestore; debugManager.flags.FilterBdfPath.set("0000:00:02.0"); VariableBackup backupOpenFull(&openFull); openFull = openWithCounter; openCounter = 10; auto hwDeviceIds = OSInterface::discoverDevices(mockExecutionEnvironment); EXPECT_EQ(1u, hwDeviceIds.size()); EXPECT_NE(nullptr, hwDeviceIds[0].get()); EXPECT_STREQ("/dev/dri/by-path/platform-4010000000.pcie-pci-0000:00:02.0-render", lastOpenedPath.c_str()); EXPECT_EQ(9, openCounter); // only one opened file } TEST_F(DrmSimpleTests, GivenSelectedExistingDeviceWhenOpenDirSuccedsThenHwDeviceIdsHaveProperPciPaths) { VariableBackup backupOpenFull(&openFull); VariableBackup backupOpenDir(&failOnOpenDir, false); VariableBackup backupEntryIndex(&entryIndex, 0u); openFull = openWithCounter; entryIndex = 0; openCounter = 1; auto hwDeviceIds = OSInterface::discoverDevices(mockExecutionEnvironment); EXPECT_EQ(1u, hwDeviceIds.size()); EXPECT_NE(nullptr, hwDeviceIds[0].get()); EXPECT_STREQ("0000:00:03.1", hwDeviceIds[0]->as()->getPciPath()); entryIndex = 0; openCounter = 2; hwDeviceIds = OSInterface::discoverDevices(mockExecutionEnvironment); EXPECT_EQ(2u, hwDeviceIds.size()); EXPECT_NE(nullptr, hwDeviceIds[0].get()); EXPECT_STREQ("0000:00:03.1", hwDeviceIds[0]->as()->getPciPath()); EXPECT_NE(nullptr, hwDeviceIds[1].get()); EXPECT_STREQ("0000:00:02.0", hwDeviceIds[1]->as()->getPciPath()); } TEST_F(DrmSimpleTests, GivenSelectedExistingDeviceWhenOpenDirFailsThenRetryOpeningRenderDevices) { VariableBackup backupOpenFull(&openFull); VariableBackup backupOpenDir(&failOnOpenDir, true); VariableBackup backupReadlink(&readLinkCalledTimes, 0); openFull = openWithCounter; openCounter = 1; auto hwDeviceIds = OSInterface::discoverDevices(mockExecutionEnvironment); EXPECT_STREQ("/dev/dri/renderD128", lastOpenedPath.c_str()); EXPECT_EQ(1u, hwDeviceIds.size()); EXPECT_NE(nullptr, hwDeviceIds[0].get()); EXPECT_STREQ("0000:00:02.0", hwDeviceIds[0]->as()->getPciPath()); EXPECT_EQ(1, readLinkCalledTimes); readLinkCalledTimes = 0; openCounter = 2; hwDeviceIds = OSInterface::discoverDevices(mockExecutionEnvironment); EXPECT_STREQ("/dev/dri/renderD129", lastOpenedPath.c_str()); EXPECT_EQ(2u, hwDeviceIds.size()); EXPECT_NE(nullptr, hwDeviceIds[0].get()); EXPECT_STREQ("0000:00:02.0", hwDeviceIds[0]->as()->getPciPath()); EXPECT_NE(nullptr, hwDeviceIds[1].get()); EXPECT_STREQ("0000:00:03.0", hwDeviceIds[1]->as()->getPciPath()); EXPECT_EQ(2, readLinkCalledTimes); } TEST_F(DrmSimpleTests, givenPrintIoctlEntriesWhenCallIoctlThenIoctlIsPrinted) { ::testing::internal::CaptureStdout(); auto drm = DrmWrap::createDrm(*(mockExecutionEnvironment.rootDeviceEnvironments[0].get())); DebugManagerStateRestore restorer; debugManager.flags.PrintIoctlEntries.set(true); uint32_t contextId = 1u; drm->destroyDrmContext(contextId); std::string output = ::testing::internal::GetCapturedStdout(); EXPECT_STREQ(output.c_str(), "IOCTL DRM_IOCTL_I915_GEM_CONTEXT_DESTROY called\nIOCTL DRM_IOCTL_I915_GEM_CONTEXT_DESTROY returns 0\n"); } struct DrmFailedIoctlTests : public ::testing::Test { void SetUp() override { if (deviceDescriptorTable[0].deviceId == 0) { GTEST_SKIP(); } } MockExecutionEnvironment mockExecutionEnvironment; }; TEST_F(DrmFailedIoctlTests, givenPrintIoctlEntriesWhenCallFailedIoctlThenExpectedIoctlIsPrinted) { ::testing::internal::CaptureStdout(); auto drm = DrmWrap::createDrm(*(mockExecutionEnvironment.rootDeviceEnvironments[0].get())); DebugManagerStateRestore restorer; debugManager.flags.PrintIoctlEntries.set(true); uint32_t contextId = 1u; uint32_t vmId = 100u; drm->queryVmId(contextId, vmId); std::string output = ::testing::internal::GetCapturedStdout(); EXPECT_STREQ(output.c_str(), "IOCTL DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM called\nIOCTL DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM returns -1, errno 9(Bad file descriptor)\n"); } TEST_F(DrmSimpleTests, givenPrintIoctlTimesWhenCallIoctlThenStatisticsAreGathered) { constexpr long long initialMin = std::numeric_limits::max(); constexpr long long initialMax = std::numeric_limits::min(); auto drm = DrmWrap::createDrm(*(mockExecutionEnvironment.rootDeviceEnvironments[0].get())); DebugManagerStateRestore restorer; debugManager.flags.PrintKmdTimes.set(true); VariableBackup backupForceExtraIoctlDuration(&forceExtraIoctlDuration, true); EXPECT_TRUE(drm->ioctlStatistics.empty()); int euTotal = 0u; uint32_t contextId = 1u; drm->getEuTotal(euTotal); EXPECT_EQ(1u, drm->ioctlStatistics.size()); drm->getEuTotal(euTotal); EXPECT_EQ(1u, drm->ioctlStatistics.size()); drm->setLowPriorityContextParam(contextId); EXPECT_EQ(2u, drm->ioctlStatistics.size()); auto euTotalData = drm->ioctlStatistics.find(DrmIoctl::getparam); ASSERT_TRUE(euTotalData != drm->ioctlStatistics.end()); EXPECT_EQ(DrmIoctl::getparam, euTotalData->first); EXPECT_EQ(2u, euTotalData->second.count); EXPECT_NE(0, euTotalData->second.totalTime); EXPECT_NE(initialMin, euTotalData->second.minTime); EXPECT_LE(euTotalData->second.minTime, euTotalData->second.maxTime); EXPECT_LE(initialMax, euTotalData->second.minTime); EXPECT_NE(initialMin, euTotalData->second.maxTime); EXPECT_NE(initialMax, euTotalData->second.maxTime); auto firstTime = euTotalData->second.totalTime; auto lowPriorityData = drm->ioctlStatistics.find(DrmIoctl::gemContextSetparam); ASSERT_TRUE(lowPriorityData != drm->ioctlStatistics.end()); EXPECT_EQ(DrmIoctl::gemContextSetparam, lowPriorityData->first); EXPECT_EQ(1u, lowPriorityData->second.count); EXPECT_NE(0, lowPriorityData->second.totalTime); EXPECT_NE(initialMin, lowPriorityData->second.minTime); EXPECT_NE(initialMax, lowPriorityData->second.minTime); EXPECT_NE(initialMin, lowPriorityData->second.maxTime); EXPECT_NE(initialMax, lowPriorityData->second.maxTime); drm->getEuTotal(euTotal); EXPECT_EQ(drm->ioctlStatistics.size(), 2u); euTotalData = drm->ioctlStatistics.find(DrmIoctl::getparam); ASSERT_TRUE(euTotalData != drm->ioctlStatistics.end()); EXPECT_EQ(DrmIoctl::getparam, euTotalData->first); EXPECT_EQ(3u, euTotalData->second.count); EXPECT_NE(0u, euTotalData->second.totalTime); auto secondTime = euTotalData->second.totalTime; EXPECT_GT(secondTime, firstTime); lowPriorityData = drm->ioctlStatistics.find(DrmIoctl::gemContextSetparam); ASSERT_TRUE(lowPriorityData != drm->ioctlStatistics.end()); EXPECT_EQ(DrmIoctl::gemContextSetparam, lowPriorityData->first); EXPECT_EQ(1u, lowPriorityData->second.count); EXPECT_NE(0, lowPriorityData->second.totalTime); drm->destroyDrmContext(contextId); EXPECT_EQ(3u, drm->ioctlStatistics.size()); euTotalData = drm->ioctlStatistics.find(DrmIoctl::getparam); ASSERT_TRUE(euTotalData != drm->ioctlStatistics.end()); EXPECT_EQ(DrmIoctl::getparam, euTotalData->first); EXPECT_EQ(3u, euTotalData->second.count); EXPECT_NE(0, euTotalData->second.totalTime); lowPriorityData = drm->ioctlStatistics.find(DrmIoctl::gemContextSetparam); ASSERT_TRUE(lowPriorityData != drm->ioctlStatistics.end()); EXPECT_EQ(DrmIoctl::gemContextSetparam, lowPriorityData->first); EXPECT_EQ(1u, lowPriorityData->second.count); EXPECT_NE(0, lowPriorityData->second.totalTime); auto destroyData = drm->ioctlStatistics.find(DrmIoctl::gemContextDestroy); ASSERT_TRUE(destroyData != drm->ioctlStatistics.end()); EXPECT_EQ(DrmIoctl::gemContextDestroy, destroyData->first); EXPECT_EQ(1u, destroyData->second.count); EXPECT_NE(0, destroyData->second.totalTime); ::testing::internal::CaptureStdout(); drm.reset(); std::string output = ::testing::internal::GetCapturedStdout(); EXPECT_STRNE("", output.c_str()); std::string_view requestString("Request"); std::string_view totalTimeString("Total time(ns)"); std::string_view countString("Count"); std::string_view avgTimeString("Avg time per ioctl"); std::string_view minString("Min"); std::string_view maxString("Max"); std::size_t position = output.find(requestString); EXPECT_NE(std::string::npos, position); position += requestString.size(); position = output.find(totalTimeString, position); EXPECT_NE(std::string::npos, position); position += totalTimeString.size(); position = output.find(countString, position); EXPECT_NE(std::string::npos, position); position += countString.size(); position = output.find(avgTimeString, position); EXPECT_NE(std::string::npos, position); position += avgTimeString.size(); position = output.find(minString, position); EXPECT_NE(std::string::npos, position); position += minString.size(); position = output.find(maxString, position); EXPECT_NE(std::string::npos, position); } TEST_F(DrmSimpleTests, GivenSelectedNonExistingDeviceWhenOpenDirFailsThenRetryOpeningRenderDevicesAndNoDevicesAreCreated) { VariableBackup backupOpenFull(&openFull); VariableBackup backupOpenDir(&failOnOpenDir, true); openFull = openWithCounter; openCounter = 0; auto hwDeviceIds = OSInterface::discoverDevices(mockExecutionEnvironment); EXPECT_EQ(0u, hwDeviceIds.size()); } TEST_F(DrmSimpleTests, GivenFailingOpenDirAndMultipleAvailableDevicesWhenCreateMultipleRootDevicesFlagIsSetThenTheFlagIsRespected) { DebugManagerStateRestore stateRestore; VariableBackup backupOpenFull(&openFull); VariableBackup backupOpenDir(&failOnOpenDir, true); VariableBackup backupReadlink(&readLinkCalledTimes, 0); openFull = openWithCounter; const uint32_t requestedNumRootDevices = 2u; debugManager.flags.CreateMultipleRootDevices.set(requestedNumRootDevices); openCounter = 4; auto hwDeviceIds = OSInterface::discoverDevices(mockExecutionEnvironment); EXPECT_STREQ("/dev/dri/renderD129", lastOpenedPath.c_str()); EXPECT_EQ(requestedNumRootDevices, hwDeviceIds.size()); EXPECT_NE(nullptr, hwDeviceIds[0].get()); EXPECT_STREQ("0000:00:02.0", hwDeviceIds[0]->as()->getPciPath()); EXPECT_NE(nullptr, hwDeviceIds[1].get()); EXPECT_STREQ("0000:00:03.0", hwDeviceIds[1]->as()->getPciPath()); } TEST_F(DrmSimpleTests, GivenMultipleAvailableDevicesWhenCreateMultipleRootDevicesFlagIsSetThenTheFlagIsRespected) { DebugManagerStateRestore stateRestore; VariableBackup backupOpenFull(&openFull); openFull = openWithCounter; const uint32_t requestedNumRootDevices = 2u; debugManager.flags.CreateMultipleRootDevices.set(requestedNumRootDevices); openCounter = 4; auto hwDeviceIds = OSInterface::discoverDevices(mockExecutionEnvironment); EXPECT_STREQ("/dev/dri/by-path/platform-4010000000.pcie-pci-0000:00:02.0-render", lastOpenedPath.c_str()); EXPECT_EQ(requestedNumRootDevices, hwDeviceIds.size()); EXPECT_NE(nullptr, hwDeviceIds[0].get()); EXPECT_STREQ("0000:00:03.1", hwDeviceIds[0]->as()->getPciPath()); EXPECT_NE(nullptr, hwDeviceIds[1].get()); EXPECT_STREQ("0000:00:02.0", hwDeviceIds[1]->as()->getPciPath()); } TEST_F(DrmTests, GivenSelectedIncorectDeviceByDeviceIdWhenGetDeviceFdThenFail) { DebugManagerStateRestore stateRestore; debugManager.flags.FilterDeviceId.set("invalid"); auto drm1 = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_EQ(drm1, nullptr); } TEST_F(DrmTests, GivenSelectedCorrectDeviceByDeviceIdWhenGetDeviceFdThenSucceed) { DebugManagerStateRestore stateRestore; std::stringstream deviceIdStr; deviceIdStr << std::hex << deviceId; debugManager.flags.FilterDeviceId.set(deviceIdStr.str()); auto drm1 = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_NE(drm1, nullptr); } TEST_F(DrmSimpleTests, givenUseVmBindFlagWhenOverrideBindSupportThenReturnProperValue) { DebugManagerStateRestore dbgRestorer; bool useVmBind = false; debugManager.flags.UseVmBind.set(1); Drm::overrideBindSupport(useVmBind); EXPECT_TRUE(useVmBind); debugManager.flags.UseVmBind.set(0); Drm::overrideBindSupport(useVmBind); EXPECT_FALSE(useVmBind); debugManager.flags.UseVmBind.set(-1); Drm::overrideBindSupport(useVmBind); EXPECT_FALSE(useVmBind); } TEST_F(DrmTests, GivenErrorCodeWhenCreatingDrmThenDrmCreatedOnlyWithSpecificErrors) { auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_NE(drm, nullptr); GetParam getParam{}; int lDeviceId; VariableBackup backupIoctlCnt(&ioctlCnt); VariableBackup backupIoctlSeq(&ioctlSeq[0]); ioctlCnt = 0; ioctlSeq[0] = -1; errno = EINTR; // check if device works, although there was EINTR error from KMD getParam.param = I915_PARAM_CHIPSET_ID; getParam.value = &lDeviceId; auto ret = drm->ioctl(DrmIoctl::getparam, &getParam); EXPECT_EQ(0, ret); EXPECT_EQ(deviceId, lDeviceId); ioctlCnt = 0; ioctlSeq[0] = -1; errno = EAGAIN; // check if device works, although there was EAGAIN error from KMD getParam.param = I915_PARAM_CHIPSET_ID; getParam.value = &lDeviceId; ret = drm->ioctl(DrmIoctl::getparam, &getParam); EXPECT_EQ(0, ret); EXPECT_EQ(deviceId, lDeviceId); ioctlCnt = 0; ioctlSeq[0] = -1; errno = EBUSY; // check if device works, although there was EBUSY error from KMD getParam.param = I915_PARAM_CHIPSET_ID; getParam.value = &lDeviceId; ret = drm->ioctl(DrmIoctl::getparam, &getParam); EXPECT_EQ(0, ret); EXPECT_EQ(deviceId, lDeviceId); ioctlCnt = 0; ioctlSeq[0] = -1; errno = 0; // we failed with any other error code getParam.param = I915_PARAM_CHIPSET_ID; getParam.value = &lDeviceId; ret = drm->ioctl(DrmIoctl::getparam, &getParam); EXPECT_EQ(-1, ret); EXPECT_EQ(deviceId, lDeviceId); } TEST_F(DrmTests, WhenCreatingTwiceThenDifferentDrmReturned) { auto drm1 = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_NE(drm1, nullptr); auto drm2 = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_NE(drm2, nullptr); EXPECT_NE(drm1, drm2); } TEST_F(DrmTests, WhenDriDeviceFoundThenDrmCreatedOnFallback) { VariableBackup backupHaveDri(&haveDri); haveDri = 1; auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_NE(drm, nullptr); } TEST_F(DrmTests, GivenNoDeviceWhenCreatingDrmThenNullIsReturned) { VariableBackup backupHaveDri(&haveDri); haveDri = -1; auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_EQ(drm, nullptr); } TEST_F(DrmTests, GivenUnknownDeviceWhenCreatingDrmThenNullIsReturned) { DebugManagerStateRestore dbgRestorer; debugManager.flags.PrintDebugMessages.set(true); VariableBackup backupDeviceId(&deviceId); VariableBackup backupRevisionId(&revisionId); deviceId = -1; revisionId = -1; ::testing::internal::CaptureStderr(); ::testing::internal::CaptureStdout(); auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_EQ(drm, nullptr); std::string errStr = ::testing::internal::GetCapturedStderr(); EXPECT_TRUE(hasSubstr(errStr, std::string("FATAL: Unknown device: deviceId: ffff, revisionId: ffff"))); ::testing::internal::GetCapturedStdout(); } TEST_F(DrmTests, GivenKnownDeviceWhenCreatingDrmThenHwInfoIsProperlySet) { VariableBackup backupRevisionId(&revisionId); revisionId = 123; auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_NE(drm, nullptr); EXPECT_EQ(revisionId, mockRootDeviceEnvironment->getHardwareInfo()->platform.usRevId); EXPECT_EQ(deviceId, mockRootDeviceEnvironment->getHardwareInfo()->platform.usDeviceID); } TEST_F(DrmTests, WhenCantFindDeviceIdThenDrmIsNotCreated) { VariableBackup backupFailOnDeviceId(&failOnDeviceId); failOnDeviceId = -1; auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_EQ(drm, nullptr); } TEST_F(DrmTests, WhenCantQueryEuCountThenDrmIsNotCreated) { VariableBackup backupfailOnEuTotal(&failOnEuTotal); failOnEuTotal = -1; auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_EQ(drm, nullptr); } TEST_F(DrmTests, WhenCantQuerySubsliceCountThenDrmIsNotCreated) { VariableBackup backupfailOnSubsliceTotal(&failOnSubsliceTotal); failOnSubsliceTotal = -1; auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_EQ(drm, nullptr); } TEST_F(DrmTests, WhenCantQueryRevisionIdThenDrmIsNotCreated) { VariableBackup backupFailOnRevisionId(&failOnRevisionId); failOnRevisionId = -1; auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_EQ(drm, nullptr); } TEST_F(DrmTests, GivenFailOnParamBoostWhenCreatingDrmThenDrmIsCreated) { VariableBackup backupFailOnParamBoost(&failOnParamBoost); failOnParamBoost = -1; auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); // non-fatal error - issue warning only EXPECT_NE(drm, nullptr); } TEST_F(DrmTests, GivenFailOnContextCreateWhenCreatingDrmThenDrmIsCreated) { VariableBackup backupFailOnContextCreate(&failOnContextCreate); auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_NE(drm, nullptr); failOnContextCreate = -1; EXPECT_EQ(-1, drm->createDrmContext(1, false, false)); EXPECT_FALSE(drm->isPreemptionSupported()); failOnContextCreate = 0; } TEST_F(DrmTests, GivenFailOnSetPriorityWhenCreatingDrmThenDrmIsCreated) { VariableBackup backupFailOnSetPriority(&failOnSetPriority); auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_NE(drm, nullptr); failOnSetPriority = -1; auto drmContext = drm->createDrmContext(1, false, false); EXPECT_THROW(drm->setLowPriorityContextParam(drmContext), std::exception); EXPECT_FALSE(drm->isPreemptionSupported()); failOnSetPriority = 0; } TEST_F(DrmTests, WhenCantQueryDrmVersionThenDrmIsNotCreated) { VariableBackup backupFailOnDrmVersion(&failOnDrmVersion); failOnDrmVersion = -1; auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_EQ(drm, nullptr); failOnDrmVersion = 0; } TEST_F(DrmTests, GivenInvalidDrmVersionNameWhenCreatingDrmThenNullIsReturned) { VariableBackup backupFailOnDrmVersion(&failOnDrmVersion); strcpy(providedDrmVersion, "NA"); auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_EQ(drm, nullptr); failOnDrmVersion = 0; strcpy(providedDrmVersion, "i915"); } TEST_F(DrmTests, whenDrmIsCreatedThenSetMemoryRegionsDoesntFailAndDrmObjectIsReturned) { DebugManagerStateRestore restore; debugManager.flags.EnableLocalMemory.set(1); auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_NE(drm, nullptr); } TEST(AllocatorHelper, givenExpectedSizeToReserveWhenGetSizeToReserveCalledThenExpectedValueReturned) { EXPECT_EQ((maxNBitValue(47) + 1) / 4, NEO::getSizeToReserve()); } TEST(DrmMemoryManagerCreate, whenCallCreateMemoryManagerThenDrmMemoryManagerIsCreated) { DebugManagerStateRestore restorer; debugManager.flags.OverridePatIndex.set(0); MockExecutionEnvironment mockExecutionEnvironment; auto drm = new DrmMockSuccess(fakeFd, *mockExecutionEnvironment.rootDeviceEnvironments[0]); drm->setupIoctlHelper(defaultHwInfo->platform.eProductFamily); mockExecutionEnvironment.rootDeviceEnvironments[0]->osInterface = std::make_unique(); mockExecutionEnvironment.rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr(drm)); auto drmMemoryManager = MemoryManager::createMemoryManager(mockExecutionEnvironment, DriverModelType::unknown); EXPECT_NE(nullptr, drmMemoryManager.get()); mockExecutionEnvironment.memoryManager = std::move(drmMemoryManager); } TEST(DrmMemoryManagerCreate, givenEnableHostPtrValidationSetToZeroWhenCreateDrmMemoryManagerThenHostPtrValidationIsDisabled) { DebugManagerStateRestore restorer; debugManager.flags.EnableHostPtrValidation.set(0); debugManager.flags.EnableGemCloseWorker.set(0); debugManager.flags.OverridePatIndex.set(0); VariableBackup backup(&ultHwConfig); ultHwConfig.forceOsAgnosticMemoryManager = false; MockExecutionEnvironment mockExecutionEnvironment; auto drm = new DrmMockSuccess(fakeFd, *mockExecutionEnvironment.rootDeviceEnvironments[0]); drm->setupIoctlHelper(defaultHwInfo->platform.eProductFamily); mockExecutionEnvironment.rootDeviceEnvironments[0]->osInterface = std::make_unique(); mockExecutionEnvironment.rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr(drm)); auto drmMemoryManager = MemoryManager::createMemoryManager(mockExecutionEnvironment, DriverModelType::unknown); EXPECT_NE(nullptr, drmMemoryManager.get()); EXPECT_FALSE(static_cast(drmMemoryManager.get())->isValidateHostMemoryEnabled()); mockExecutionEnvironment.memoryManager = std::move(drmMemoryManager); } TEST(OsInterfaceTests, givenOsInterfaceWhenEnableLocalMemoryIsSpecifiedThenItIsSetToTrueOn64Bit) { EXPECT_TRUE(OSInterface::osEnableLocalMemory); } TEST_F(DrmTests, whenDrmIsCreatedWithMultipleSubDevicesThenCreateMultipleVirtualMemoryAddressSpaces) { DebugManagerStateRestore restore; debugManager.flags.CreateMultipleSubDevices.set(2); auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_NE(drm, nullptr); if (drm->isPerContextVMRequired()) { GTEST_SKIP(); } auto numSubDevices = GfxCoreHelper::getSubDevicesCount(mockRootDeviceEnvironment->getHardwareInfo()); for (auto id = 0u; id < numSubDevices; id++) { EXPECT_EQ(id + 1, drm->getVirtualMemoryAddressSpace(id)); } } TEST_F(DrmTests, givenDebuggingEnabledWhenDrmIsCreatedThenPerContextVMIsTrueGetVirtualMemoryAddressSpaceReturnsZeroAndVMsAreNotCreated) { DebugManagerStateRestore restore; debugManager.flags.CreateMultipleSubDevices.set(2); debugManager.flags.UseVmBind.set(1); mockExecutionEnvironment.setDebuggingMode(NEO::DebuggingMode::online); auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); ASSERT_NE(drm, nullptr); if (drm->isVmBindAvailable()) { EXPECT_TRUE(drm->isPerContextVMRequired()); auto numSubDevices = GfxCoreHelper::getSubDevicesCount(mockRootDeviceEnvironment->getHardwareInfo()); for (auto id = 0u; id < numSubDevices; id++) { EXPECT_EQ(0u, drm->getVirtualMemoryAddressSpace(id)); } EXPECT_EQ(0u, static_cast(drm.get())->virtualMemoryIds.size()); } } TEST_F(DrmTests, givenEnabledDebuggingAndVmBindNotAvailableWhenDrmIsCreatedThenPerContextVMIsFalseVMsAreCreatedAndDebugMessageIsPrinted) { DebugManagerStateRestore restore; ::testing::internal::CaptureStderr(); ::testing::internal::CaptureStdout(); debugManager.flags.CreateMultipleSubDevices.set(2); debugManager.flags.UseVmBind.set(0); debugManager.flags.PrintDebugMessages.set(true); mockRootDeviceEnvironment->executionEnvironment.setDebuggingMode(NEO::DebuggingMode::online); auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_NE(drm, nullptr); if (drm->isPerContextVMRequired()) { ::testing::internal::GetCapturedStdout(); ::testing::internal::GetCapturedStderr(); GTEST_SKIP(); } auto numSubDevices = GfxCoreHelper::getSubDevicesCount(mockRootDeviceEnvironment->getHardwareInfo()); for (auto id = 0u; id < numSubDevices; id++) { EXPECT_NE(0u, drm->getVirtualMemoryAddressSpace(id)); } EXPECT_NE(0u, static_cast(drm.get())->virtualMemoryIds.size()); debugManager.flags.PrintDebugMessages.set(false); ::testing::internal::GetCapturedStdout(); std::string errStr = ::testing::internal::GetCapturedStderr(); EXPECT_TRUE(hasSubstr(errStr, std::string("WARNING: Debugging not supported\n"))); } TEST_F(DrmTests, givenDrmIsCreatedWhenCreateVirtualMemoryFailsThenReturnVirtualMemoryIdZeroAndPrintDebugMessage) { DebugManagerStateRestore dbgRestorer; debugManager.flags.PrintDebugMessages.set(true); VariableBackup backupFailOnVirtualMemoryCreate(&failOnVirtualMemoryCreate); failOnVirtualMemoryCreate = -1; ::testing::internal::CaptureStderr(); ::testing::internal::CaptureStdout(); auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_NE(drm, nullptr); EXPECT_EQ(0u, drm->getVirtualMemoryAddressSpace(0)); EXPECT_EQ(0u, static_cast(drm.get())->virtualMemoryIds.size()); std::string errStr = ::testing::internal::GetCapturedStderr(); if (!drm->isPerContextVMRequired()) { EXPECT_TRUE(hasSubstr(errStr, std::string("INFO: Device doesn't support GEM Virtual Memory"))); } ::testing::internal::GetCapturedStdout(); } TEST_F(DrmTests, givenDrmIsCreatedWithPerContextVmRequiredWhenCreateVirtualMemoryThenCapturedVirtualMemoryIsSettingScratchPageOptionCorrectly) { DebugManagerStateRestore dbgRestorer; debugManager.flags.PrintDebugMessages.set(true); debugManager.flags.DisableScratchPages.set(true); debugManager.flags.GpuFaultCheckThreshold.set(10); VariableBackup backupCaptureVirtualMemoryCreate(&captureVirtualMemoryCreate); VariableBackup backupCapturedVmCreate(&capturedVmCreate); captureVirtualMemoryCreate = 1; capturedVmCreate = {}; auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_NE(drm, nullptr); auto disableScratch = drm.get()->checkToDisableScratchPage(); auto ioctlHelper = drm.get()->getIoctlHelper(); for (auto ctl : capturedVmCreate) { EXPECT_NE(0u, (ctl.flags & ioctlHelper->getFlagsForVmCreate(disableScratch, false, false))); } } TEST(SysCalls, WhenSysCallsPollCalledThenCallIsRedirectedToOs) { struct pollfd pollFd; pollFd.fd = 0; pollFd.events = 0; auto result = NEO::SysCalls::poll(&pollFd, 1, 0); EXPECT_LE(0, result); } TEST(SysCalls, WhenSysCallsFstatCalledThenCallIsRedirectedToOs) { struct stat st = {}; auto result = NEO::SysCalls::fstat(0, &st); EXPECT_EQ(0, result); } TEST(SysCalls, WhenSysCallsGetNumThreadsCalledThenCallIsRedirectedToOs) { auto result = NEO::SysCalls::getNumThreads(); EXPECT_GT(result, 0u); } bool enableAlarm = true; int main(int argc, char **argv) { bool useDefaultListener = false; ::testing::InitGoogleTest(&argc, argv); // parse remaining args assuming they're mine for (int i = 1; i < argc; ++i) { if (!strcmp("--disable_default_listener", argv[i])) { useDefaultListener = false; } else if (!strcmp("--enable_default_listener", argv[i])) { useDefaultListener = true; } else if (!strcmp("--disable_alarm", argv[i])) { enableAlarm = false; } } if (useDefaultListener == false) { auto &listeners = ::testing::UnitTest::GetInstance()->listeners(); auto defaultListener = listeners.default_result_printer(); auto customEventListener = new CCustomEventListener(defaultListener); listeners.Release(defaultListener); listeners.Append(customEventListener); } defaultHwInfo = std::make_unique(); *defaultHwInfo = DEFAULT_TEST_PLATFORM::hwInfo; initializeTestedDevice(); Os::dxcoreDllName = ""; int sigOut = setAlarm(enableAlarm); if (sigOut != 0) return sigOut; auto retVal = RUN_ALL_TESTS(); return retVal; } TEST_F(DrmTests, whenCreateDrmIsCalledThenProperHwInfoIsSetup) { auto oldHwInfo = mockRootDeviceEnvironment->getMutableHardwareInfo(); *oldHwInfo = {}; auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); EXPECT_NE(drm, nullptr); auto currentHwInfo = mockRootDeviceEnvironment->getHardwareInfo(); EXPECT_NE(IGFX_UNKNOWN, currentHwInfo->platform.eProductFamily); EXPECT_NE(IGFX_UNKNOWN_CORE, currentHwInfo->platform.eRenderCoreFamily); EXPECT_LT(0u, currentHwInfo->gtSystemInfo.EUCount); EXPECT_LT(0u, currentHwInfo->gtSystemInfo.SubSliceCount); } TEST(DirectSubmissionControllerTest, whenCheckDirectSubmissionControllerSupportThenReturnsTrue) { EXPECT_TRUE(DirectSubmissionController::isSupported()); } TEST(CommandQueueTest, whenCheckEngineRoundRobinAssignThenReturnsTrue) { EXPECT_TRUE(CommandQueue::isAssignEngineRoundRobinEnabled()); } TEST(CommandQueueTest, whenCheckEngineTimestampWaitEnabledThenReturnsTrue) { EXPECT_TRUE(CommandQueue::isTimestampWaitEnabled()); } TEST(DeviceTest, whenCheckBlitSplitEnabledThenReturnsTrue) { EXPECT_TRUE(Device::isBlitSplitEnabled()); } TEST(DeviceTest, givenCsrHwWhenCheckIsInitDeviceWithFirstSubmissionEnabledThenReturnsTrue) { EXPECT_TRUE(Device::isInitDeviceWithFirstSubmissionEnabled(CommandStreamReceiverType::hardware)); } TEST(DeviceTest, givenCsrNonHwWhenCheckIsInitDeviceWithFirstSubmissionEnabledThenReturnsTrue) { EXPECT_FALSE(Device::isInitDeviceWithFirstSubmissionEnabled(CommandStreamReceiverType::tbx)); } TEST(PlatformsDestructor, whenGlobalPlatformsDestructorIsCalledThenGlobalPlatformsAreDestroyed) { EXPECT_NE(nullptr, platformsImpl); platformsDestructor(); EXPECT_EQ(nullptr, platformsImpl); platformsImpl = new std::vector>; } TEST_F(DrmTests, givenValidPciPathThenPciBusInfoIsAvailable) { VariableBackup backupOpenFull(&openFull); VariableBackup backupOpenDir(&failOnOpenDir, false); VariableBackup backupEntryIndex(&entryIndex, 0u); openFull = openWithCounter; entryIndex = 1; openCounter = 2; auto drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); ASSERT_NE(drm, nullptr); EXPECT_EQ(drm->getPciBusInfo().pciDomain, 0u); EXPECT_EQ(drm->getPciBusInfo().pciBus, 0u); EXPECT_EQ(drm->getPciBusInfo().pciDevice, 3u); EXPECT_EQ(drm->getPciBusInfo().pciFunction, 1u); entryIndex = 2; openCounter = 1; drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); ASSERT_NE(drm, nullptr); EXPECT_EQ(drm->getPciBusInfo().pciDomain, 0u); EXPECT_EQ(drm->getPciBusInfo().pciBus, 0u); EXPECT_EQ(drm->getPciBusInfo().pciDevice, 2u); EXPECT_EQ(drm->getPciBusInfo().pciFunction, 0u); uint32_t referenceData[4][4] = { {0x0a00, 0x00, 0x03, 0x1}, {0x0000, 0xb3, 0x03, 0x1}, {0x0000, 0x00, 0xb3, 0x1}, {0x0000, 0x00, 0x03, 0xa}}; for (uint32_t idx = 7; idx < 11; idx++) { entryIndex = idx; openCounter = 1; drm = DrmWrap::createDrm(*mockRootDeviceEnvironment); ASSERT_NE(drm, nullptr); EXPECT_EQ(drm->getPciBusInfo().pciDomain, referenceData[idx - 7][0]); EXPECT_EQ(drm->getPciBusInfo().pciBus, referenceData[idx - 7][1]); EXPECT_EQ(drm->getPciBusInfo().pciDevice, referenceData[idx - 7][2]); EXPECT_EQ(drm->getPciBusInfo().pciFunction, referenceData[idx - 7][3]); } } TEST_F(DrmTests, givenInValidPciPathThenNothingIsReturned) { VariableBackup backupOpenFull(&openFull); VariableBackup backupOpenDir(&failOnOpenDir, false); VariableBackup backupEntryIndex(&entryIndex, 0u); openFull = openWithCounter; entryIndex = 11; openCounter = 1; auto hwDeviceIds = OSInterface::discoverDevices(mockExecutionEnvironment); EXPECT_TRUE(hwDeviceIds.empty()); entryIndex = 12; openCounter = 1; hwDeviceIds = OSInterface::discoverDevices(mockExecutionEnvironment); EXPECT_TRUE(hwDeviceIds.empty()); entryIndex = 13; openCounter = 1; hwDeviceIds = OSInterface::discoverDevices(mockExecutionEnvironment); EXPECT_TRUE(hwDeviceIds.empty()); }