From d8f99161dda51bae829e5260b37cf6b8a35ac5e7 Mon Sep 17 00:00:00 2001 From: Mateusz Hoppe Date: Fri, 17 Mar 2023 11:50:23 +0000 Subject: [PATCH] fix: create VMs with correct flags when perContextVms used Related-To: NEO-7813 Signed-off-by: Mateusz Hoppe --- shared/source/os_interface/linux/drm_neo.h | 2 +- .../os_interface/linux/os_context_linux.cpp | 23 +++++++----- shared/test/common/libult/linux/drm_mock.h | 6 ++++ .../linux/drm_buffer_object_tests.cpp | 26 +++++++++----- .../linux/drm_debug_prelim_tests.cpp | 2 +- .../linux/drm_query_prelim_tests.cpp | 17 +++++++++ .../os_interface/linux/drm_tests.cpp | 36 +++++++++++++++---- .../linux/drm_with_prelim_tests.cpp | 27 +++++++++++++- 8 files changed, 112 insertions(+), 27 deletions(-) diff --git a/shared/source/os_interface/linux/drm_neo.h b/shared/source/os_interface/linux/drm_neo.h index 6953b4ae46..4e0e657f85 100644 --- a/shared/source/os_interface/linux/drm_neo.h +++ b/shared/source/os_interface/linux/drm_neo.h @@ -107,7 +107,7 @@ class Drm : public DriverModel { return adapterBDF; } int queryAdapterBDF(); - int createDrmVirtualMemory(uint32_t &drmVmId); + MOCKABLE_VIRTUAL int createDrmVirtualMemory(uint32_t &drmVmId); void destroyDrmVirtualMemory(uint32_t drmVmId); MOCKABLE_VIRTUAL int createDrmContext(uint32_t drmVmId, bool isDirectSubmissionRequested, bool isCooperativeContextRequested); void destroyDrmContext(uint32_t drmContextId); diff --git a/shared/source/os_interface/linux/os_context_linux.cpp b/shared/source/os_interface/linux/os_context_linux.cpp index 27139d571c..2f5f424f43 100644 --- a/shared/source/os_interface/linux/os_context_linux.cpp +++ b/shared/source/os_interface/linux/os_context_linux.cpp @@ -49,21 +49,26 @@ bool OsContextLinux::initializeContext() { for (auto deviceIndex = 0u; deviceIndex < deviceBitfield.size(); deviceIndex++) { if (deviceBitfield.test(deviceIndex)) { auto drmVmId = drm.getVirtualMemoryAddressSpace(deviceIndex); + + if (drm.isPerContextVMRequired()) { + drmVmId = deviceIndex; + [[maybe_unused]] auto ret = drm.createDrmVirtualMemory(drmVmId); + DEBUG_BREAK_IF(drmVmId == 0); + DEBUG_BREAK_IF(ret != 0); + if (ret != 0) { + return false; + } + + UNRECOVERABLE_IF(this->drmVmIds.size() <= deviceIndex); + this->drmVmIds[deviceIndex] = drmVmId; + } + auto drmContextId = drm.getIoctlHelper()->createDrmContext(drm, *this, drmVmId, deviceIndex); if (drmContextId < 0) { return false; } this->drmContextIds.push_back(drmContextId); - - if (drm.isPerContextVMRequired()) { - [[maybe_unused]] auto ret = drm.queryVmId(drmContextId, drmVmId); - DEBUG_BREAK_IF(drmVmId == 0); - DEBUG_BREAK_IF(ret != 0); - - UNRECOVERABLE_IF(this->drmVmIds.size() <= deviceIndex); - this->drmVmIds[deviceIndex] = drmVmId; - } } } return true; diff --git a/shared/test/common/libult/linux/drm_mock.h b/shared/test/common/libult/linux/drm_mock.h index daee7786cb..fb73095401 100644 --- a/shared/test/common/libult/linux/drm_mock.h +++ b/shared/test/common/libult/linux/drm_mock.h @@ -121,6 +121,11 @@ class DrmMock : public Drm { return 0; } + int createDrmVirtualMemory(uint32_t &drmVmId) override { + createDrmVmCalled++; + return Drm::createDrmVirtualMemory(drmVmId); + } + bool isVmBindAvailable() override { if (callBaseIsVmBindAvailable) { return Drm::isVmBindAvailable(); @@ -201,6 +206,7 @@ class DrmMock : public Drm { GemContextParam receivedContextParamRequest = {}; uint64_t receivedRecoverableContextValue = std::numeric_limits::max(); uint64_t requestSetVmId = std::numeric_limits::max(); + int createDrmVmCalled = 0; bool queryPageFaultSupportCalled = false; diff --git a/shared/test/unit_test/os_interface/linux/drm_buffer_object_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_buffer_object_tests.cpp index 706dffc4d9..696f4eac4d 100644 --- a/shared/test/unit_test/os_interface/linux/drm_buffer_object_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_buffer_object_tests.cpp @@ -392,8 +392,10 @@ TEST(DrmBufferObject, givenDrmIoctlReturnsErrorNotSupportedThenBufferObjectRetur executionEnvironment->calculateMaxOsContextCount(); executionEnvironment->rootDeviceEnvironments[0]->osInterface = std::make_unique(); - DrmMockReturnErrorNotSupported *drm = new DrmMockReturnErrorNotSupported(*executionEnvironment->rootDeviceEnvironments[0]); - + DrmMock *drm = new DrmMock(*executionEnvironment->rootDeviceEnvironments[0]); + drm->execBufferResult = -1; + drm->errnoRetVal = EOPNOTSUPP; + drm->baseErrno = false; executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr(drm)); executionEnvironment->rootDeviceEnvironments[0]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*drm, 0u); @@ -463,6 +465,7 @@ TEST(DrmBufferObject, givenPrintBOBindingResultWhenBOBindAndUnbindSucceedsThenPr executionEnvironment->rootDeviceEnvironments[0]->osInterface = std::make_unique(); auto drm = new DrmMockToSucceedBindBufferObject(*executionEnvironment->rootDeviceEnvironments[0]); + drm->latestCreatedVmId = 1; executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr(drm)); executionEnvironment->rootDeviceEnvironments[0]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*drm, 0u); @@ -484,15 +487,18 @@ TEST(DrmBufferObject, givenPrintBOBindingResultWhenBOBindAndUnbindSucceedsThenPr EXPECT_TRUE(bo.bindInfo[contextId][0]); std::string bindOutput = testing::internal::GetCapturedStdout(); - EXPECT_STREQ(bindOutput.c_str(), "bind BO-0 to VM 0, drmVmId = 1, range: 0 - 0, size: 0, result: 0\n"); - + std::stringstream expected; + expected << "bind BO-0 to VM 0, drmVmId = " << drm->latestCreatedVmId << ", range: 0 - 0, size: 0, result: 0\n"; + EXPECT_STREQ(bindOutput.c_str(), expected.str().c_str()) << bindOutput; + expected.str(""); testing::internal::CaptureStdout(); bo.unbind(osContext, 0); EXPECT_FALSE(bo.bindInfo[contextId][0]); std::string unbindOutput = testing::internal::GetCapturedStdout(); - EXPECT_STREQ(unbindOutput.c_str(), "unbind BO-0 from VM 0, drmVmId = 1, range: 0 - 0, size: 0, result: 0\n"); + expected << "unbind BO-0 from VM 0, drmVmId = " << drm->latestCreatedVmId << ", range: 0 - 0, size: 0, result: 0\n"; + EXPECT_STREQ(unbindOutput.c_str(), expected.str().c_str()) << unbindOutput; } TEST(DrmBufferObject, givenPrintBOBindingResultWhenBOBindAndUnbindFailsThenPrintDebugInformationAboutBOBindingResultWithErrno) { @@ -516,6 +522,7 @@ TEST(DrmBufferObject, givenPrintBOBindingResultWhenBOBindAndUnbindFailsThenPrint executionEnvironment->rootDeviceEnvironments[0]->osInterface = std::make_unique(); auto drm = new DrmMockToFailBindBufferObject(*executionEnvironment->rootDeviceEnvironments[0]); + drm->latestCreatedVmId = 1; executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr(drm)); executionEnvironment->rootDeviceEnvironments[0]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*drm, 0u); @@ -537,8 +544,10 @@ TEST(DrmBufferObject, givenPrintBOBindingResultWhenBOBindAndUnbindFailsThenPrint EXPECT_FALSE(bo.bindInfo[contextId][0]); std::string bindOutput = testing::internal::GetCapturedStderr(); - EXPECT_TRUE(hasSubstr(bindOutput, "bind BO-0 to VM 0, drmVmId = 1, range: 0 - 0, size: 0, result: -1, errno: 22")); - + std::stringstream expected; + expected << "bind BO-0 to VM 0, drmVmId = " << drm->latestCreatedVmId << ", range: 0 - 0, size: 0, result: -1, errno: 22\n"; + EXPECT_TRUE(hasSubstr(expected.str(), expected.str())) << bindOutput; + expected.str(""); testing::internal::CaptureStderr(); bo.bindInfo[contextId][0] = true; @@ -546,7 +555,8 @@ TEST(DrmBufferObject, givenPrintBOBindingResultWhenBOBindAndUnbindFailsThenPrint EXPECT_TRUE(bo.bindInfo[contextId][0]); std::string unbindOutput = testing::internal::GetCapturedStderr(); - EXPECT_TRUE(hasSubstr(unbindOutput, "unbind BO-0 from VM 0, drmVmId = 1, range: 0 - 0, size: 0, result: -1, errno: 22")); + expected << "unbind BO-0 from VM 0, drmVmId = " << drm->latestCreatedVmId << ", range: 0 - 0, size: 0, result: -1, errno: 22"; + EXPECT_TRUE(hasSubstr(unbindOutput, expected.str())) << unbindOutput; } TEST(DrmBufferObject, whenBindExtHandleAddedThenItIsStored) { diff --git a/shared/test/unit_test/os_interface/linux/drm_debug_prelim_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_debug_prelim_tests.cpp index 2b00ac6e52..c4af9822c0 100644 --- a/shared/test/unit_test/os_interface/linux/drm_debug_prelim_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_debug_prelim_tests.cpp @@ -356,7 +356,7 @@ TEST(DrmPrelimTest, givenProgramDebuggingAndContextDebugAvailableAndCCSEnginesWh EXPECT_EQ(0u, drm->passedContextDebugId); if (executionEnvironment->rootDeviceEnvironments[0]->getHardwareInfo()->gtSystemInfo.CCSInfo.NumberOfCCSEnabled > 0) { - EXPECT_EQ(4u, drm->receivedContextParamRequestCount); + EXPECT_EQ(3u, drm->receivedContextParamRequestCount); EXPECT_EQ(1u, drm->context.receivedContextCreateExtSetParamRunaloneCount); } else { EXPECT_EQ(3u, drm->receivedContextParamRequestCount); diff --git a/shared/test/unit_test/os_interface/linux/drm_query_prelim_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_query_prelim_tests.cpp index a799d8c3ee..53e8578e76 100644 --- a/shared/test/unit_test/os_interface/linux/drm_query_prelim_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_query_prelim_tests.cpp @@ -427,6 +427,23 @@ TEST(DrmBufferObjectTestPrelim, givenPageFaultSupportedWhenVmBindIsAvailableThen } } +TEST(DrmBufferObjectTestPrelim, givenContextWhenQueryingVmIdThenIoctlIsCalled) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->rootDeviceEnvironments[0]->initGmm(); + executionEnvironment->initializeMemoryManager(); + DrmQueryMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + BufferObjectMock bo(&drm, 3, 1, 0, 1); + OsContextLinux osContext(drm, 0, 0u, EngineDescriptorHelper::getDefaultDescriptor()); + osContext.ensureContextInitialized(); + + uint32_t vmId = 0; + drm.storedRetValForVmId = 10; + drm.queryVmId(0, vmId); + + EXPECT_EQ(static_cast(I915_CONTEXT_PARAM_VM), drm.receivedContextParamRequest.param); + EXPECT_EQ(static_cast(drm.storedRetValForVmId), vmId); +} + TEST(DrmBufferObjectTestPrelim, givenBufferObjectMarkedForCaptureWhenBindingThenCaptureFlagIsSet) { auto executionEnvironment = std::make_unique(); executionEnvironment->rootDeviceEnvironments[0]->initGmm(); diff --git a/shared/test/unit_test/os_interface/linux/drm_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_tests.cpp index d377fc2eb2..3fb7f3bf33 100644 --- a/shared/test/unit_test/os_interface/linux/drm_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_tests.cpp @@ -681,7 +681,7 @@ TEST(DrmTest, givenDrmWithPerContextVMRequiredWhenCreatingOsContextsThenImplicit osContext2.ensureContextInitialized(); } -TEST(DrmTest, givenPerContextVMRequiredWhenCreatingOsContextsThenImplicitVmIdPerContextIsQueriedAndStored) { +TEST(DrmTest, givenPerContextVMRequiredWhenCreatingOsContextsThenExplicitVmIsCreated) { MockExecutionEnvironment executionEnvironment{}; auto &rootEnv = *executionEnvironment.rootDeviceEnvironments[0]; rootEnv.executionEnvironment.setDebuggingMode(NEO::DebuggingMode::Online); @@ -698,10 +698,32 @@ TEST(DrmTest, givenPerContextVMRequiredWhenCreatingOsContextsThenImplicitVmIdPer auto &drmVmIds = osContext.getDrmVmIds(); EXPECT_EQ(4u, drmVmIds.size()); - EXPECT_EQ(20u, drmVmIds[0]); + EXPECT_NE(20u, drmVmIds[0]); + + EXPECT_EQ(1, drmMock.ioctlCount.gemVmCreate); + EXPECT_EQ(0u, drmMock.receivedGemVmControl.vmId); + EXPECT_EQ(drmMock.latestCreatedVmId, drmVmIds[0]); + EXPECT_EQ(1, drmMock.createDrmVmCalled); } -TEST(DrmTest, givenPerContextVMRequiredWhenCreatingOsContextForSubDeviceThenImplicitVmIdPerContextIsQueriedAndStoredAtSubDeviceIndex) { +TEST(DrmTest, givenPerContextVMRequiredWhenVmIdCreationFailsThenContextInitializationReturnsFalse) { + MockExecutionEnvironment executionEnvironment{}; + auto &rootEnv = *executionEnvironment.rootDeviceEnvironments[0]; + + DrmMock drmMock(rootEnv); + drmMock.setPerContextVMRequired(true); + + drmMock.storedRetValForVmCreate = -1; + + OsContextLinux osContext(drmMock, 0, 0u, EngineDescriptorHelper::getDefaultDescriptor()); + drmMock.createDrmVmCalled = 0; + auto status = osContext.ensureContextInitialized(); + EXPECT_EQ(1, drmMock.createDrmVmCalled); + + EXPECT_FALSE(status); +} + +TEST(DrmTest, givenPerContextVMRequiredWhenCreatingOsContextForSubDeviceThenVmIdPerContextIsCreateddAndStoredAtSubDeviceIndex) { MockExecutionEnvironment executionEnvironment{}; auto &rootEnv = *executionEnvironment.rootDeviceEnvironments[0]; rootEnv.executionEnvironment.setDebuggingMode(NEO::DebuggingMode::Online); @@ -719,13 +741,13 @@ TEST(DrmTest, givenPerContextVMRequiredWhenCreatingOsContextForSubDeviceThenImpl auto &drmVmIds = osContext.getDrmVmIds(); EXPECT_EQ(4u, drmVmIds.size()); - EXPECT_EQ(4u, drmVmIds[3]); + EXPECT_EQ(drmMock.latestCreatedVmId, drmVmIds[3]); EXPECT_EQ(0u, drmVmIds[0]); EXPECT_EQ(0u, drmVmIds[2]); } -TEST(DrmTest, givenPerContextVMRequiredWhenCreatingOsContextsForRootDeviceThenImplicitVmIdsPerContextAreQueriedAndStoredAtSubDeviceIndices) { +TEST(DrmTest, givenPerContextVMRequiredWhenCreatingOsContextsForRootDeviceThenVmIdsPerContextAreCreatedAndStoredAtSubDeviceIndices) { MockExecutionEnvironment executionEnvironment{}; auto &rootEnv = *executionEnvironment.rootDeviceEnvironments[0]; rootEnv.executionEnvironment.setDebuggingMode(NEO::DebuggingMode::Online); @@ -743,8 +765,8 @@ TEST(DrmTest, givenPerContextVMRequiredWhenCreatingOsContextsForRootDeviceThenIm auto &drmVmIds = osContext.getDrmVmIds(); EXPECT_EQ(4u, drmVmIds.size()); - EXPECT_EQ(4u, drmVmIds[0]); - EXPECT_EQ(4u, drmVmIds[1]); + EXPECT_EQ(drmMock.latestCreatedVmId - 1, drmVmIds[0]); + EXPECT_EQ(drmMock.latestCreatedVmId, drmVmIds[1]); EXPECT_EQ(0u, drmVmIds[2]); } diff --git a/shared/test/unit_test/os_interface/linux/drm_with_prelim_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_with_prelim_tests.cpp index 18b7f45410..dff6961fef 100644 --- a/shared/test/unit_test/os_interface/linux/drm_with_prelim_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_with_prelim_tests.cpp @@ -509,7 +509,6 @@ TEST_F(IoctlHelperPrelimFixture, givenProgramDebuggingAndContextDebugSupportedWh if (executionEnvironment->rootDeviceEnvironments[0]->getHardwareInfo()->gtSystemInfo.CCSInfo.NumberOfCCSEnabled > 0) { EXPECT_TRUE(drm->capturedCooperativeContextRequest); } else { - EXPECT_FALSE(drm->capturedCooperativeContextRequest); } OsContextLinux osContext2(*drm, 0, 5u, EngineDescriptorHelper::getDefaultDescriptor({aub_stream::ENGINE_RCS, EngineUsage::Cooperative})); @@ -519,6 +518,32 @@ TEST_F(IoctlHelperPrelimFixture, givenProgramDebuggingAndContextDebugSupportedWh EXPECT_TRUE(drm->capturedCooperativeContextRequest); } +TEST(IoctlHelperPrelimTest, givenProgramDebuggingAndContextDebugSupportedWhenInitializingContextThenVmIsCreatedWithAllNecessaryFlags) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->setDebuggingMode(NEO::DebuggingMode::Online); + + auto drm = std::make_unique(*executionEnvironment->rootDeviceEnvironments[0]); + drm->ioctlHelper = std::make_unique(*drm); + drm->contextDebugSupported = true; + drm->callBaseCreateDrmContext = false; + drm->bindAvailable = true; + drm->setPerContextVMRequired(true); + + executionEnvironment->rootDeviceEnvironments[0]->getMutableHardwareInfo()->platform.eProductFamily = defaultHwInfo->platform.eProductFamily; + + OsContextLinux osContext(*drm, 0, 5u, EngineDescriptorHelper::getDefaultDescriptor({aub_stream::ENGINE_RCS, EngineUsage::Regular})); + osContext.ensureContextInitialized(); + + EXPECT_FALSE(drm->receivedGemVmControl.flags & PRELIM_I915_VM_CREATE_FLAGS_DISABLE_SCRATCH); + EXPECT_TRUE(drm->receivedGemVmControl.flags & PRELIM_I915_VM_CREATE_FLAGS_USE_VM_BIND); + if (drm->hasPageFaultSupport()) { + EXPECT_TRUE(drm->receivedGemVmControl.flags & PRELIM_I915_VM_CREATE_FLAGS_ENABLE_PAGE_FAULT); + } else { + EXPECT_FALSE(drm->receivedGemVmControl.flags & PRELIM_I915_VM_CREATE_FLAGS_ENABLE_PAGE_FAULT); + } + EXPECT_EQ(1, drm->createDrmVmCalled); +} + TEST_F(IoctlHelperPrelimFixture, givenIoctlHelperWhenInitializatedThenIpVersionIsSet) { auto &ipVersion = executionEnvironment->rootDeviceEnvironments[0]->getMutableHardwareInfo()->ipVersion; ipVersion = {};