diff --git a/shared/source/os_interface/linux/drm_allocation.cpp b/shared/source/os_interface/linux/drm_allocation.cpp index 3c28036337..2456e5a55d 100644 --- a/shared/source/os_interface/linux/drm_allocation.cpp +++ b/shared/source/os_interface/linux/drm_allocation.cpp @@ -8,12 +8,14 @@ #include "shared/source/os_interface/linux/drm_allocation.h" #include "shared/source/debug_settings/debug_settings_manager.h" +#include "shared/source/helpers/basic_math.h" #include "shared/source/memory_manager/residency.h" #include "shared/source/os_interface/linux/cache_info.h" #include "shared/source/os_interface/linux/drm_buffer_object.h" #include "shared/source/os_interface/linux/drm_memory_manager.h" #include "shared/source/os_interface/linux/drm_neo.h" #include "shared/source/os_interface/linux/ioctl_helper.h" +#include "shared/source/os_interface/linux/os_context_linux.h" #include "shared/source/os_interface/os_context.h" #include @@ -232,9 +234,11 @@ void DrmAllocation::registerBOBindExtHandle(Drm *drm) { uint64_t gpuAddress = getGpuAddress(); handle = drm->registerResource(resourceClass, &gpuAddress, sizeof(gpuAddress)); } + registeredBoBindHandles.push_back(handle); auto &bos = getBOs(); + uint32_t boIndex = 0u; for (auto bo : bos) { if (bo) { @@ -246,8 +250,25 @@ void DrmAllocation::registerBOBindExtHandle(Drm *drm) { registeredBoBindHandles.push_back(cookieHandle); } + if (resourceClass == DrmResourceClass::SbaTrackingBuffer && getOsContext()) { + auto deviceIndex = [=]() -> uint32_t { + if (storageInfo.tileInstanced == true) { + return boIndex; + } + auto deviceBitfield = this->storageInfo.subDeviceBitfield; + return deviceBitfield.any() ? static_cast(Math::log2(static_cast(deviceBitfield.to_ulong()))) : 0u; + }(); + + auto contextId = getOsContext()->getOfflineDumpContextId(deviceIndex); + auto externalHandle = drm->registerResource(resourceClass, &contextId, sizeof(uint64_t)); + + bo->addBindExtHandle(externalHandle); + registeredBoBindHandles.push_back(externalHandle); + } + bo->requireImmediateBinding(true); } + boIndex++; } } } diff --git a/shared/source/os_interface/linux/drm_allocation.h b/shared/source/os_interface/linux/drm_allocation.h index 3294840855..3fa1dbe876 100644 --- a/shared/source/os_interface/linux/drm_allocation.h +++ b/shared/source/os_interface/linux/drm_allocation.h @@ -14,6 +14,7 @@ namespace NEO { class BufferObject; class OsContext; class Drm; +class OsContextLinux; enum class CachePolicy : uint32_t; enum class CacheRegion : uint16_t; @@ -110,6 +111,14 @@ class DrmAllocation : public GraphicsAllocation { size_t getMmapSize() { return this->mmapSize; } void setMmapSize(size_t size) { this->mmapSize = size; } + OsContextLinux *getOsContext() const { + return this->osContext; + } + + void setOsContext(OsContextLinux *context) { + this->osContext = context; + } + MOCKABLE_VIRTUAL int makeBOsResident(OsContext *osContext, uint32_t vmHandleId, std::vector *bufferObjects, bool bind); MOCKABLE_VIRTUAL int bindBO(BufferObject *bo, OsContext *osContext, uint32_t vmHandleId, std::vector *bufferObjects, bool bind); MOCKABLE_VIRTUAL int bindBOs(OsContext *osContext, uint32_t vmHandleId, std::vector *bufferObjects, bool bind); @@ -122,6 +131,7 @@ class DrmAllocation : public GraphicsAllocation { void registerMemoryToUnmap(void *pointer, size_t size, MemoryUnmapFunction unmapFunction); protected: + OsContextLinux *osContext = nullptr; BufferObjects bufferObjects{}; StackVec registeredBoBindHandles; MemAdviseFlags enabledMemAdviseFlags{}; diff --git a/shared/source/os_interface/linux/drm_debug.h b/shared/source/os_interface/linux/drm_debug.h index a86f55f0c1..f0bf7c6f8d 100644 --- a/shared/source/os_interface/linux/drm_debug.h +++ b/shared/source/os_interface/linux/drm_debug.h @@ -19,6 +19,7 @@ enum class DrmResourceClass : uint32_t { ModuleHeapDebugArea, ContextSaveArea, SbaTrackingBuffer, + ContextID, L0ZebinModule, MaxSize }; @@ -61,6 +62,7 @@ inline const ClassNamesArray classNamesToUuid = {std::make_pair("I915_UUID_CLASS std::make_pair("I915_UUID_L0_MODULE_AREA", "a411e82e-16c9-58b7-bfb5-b209b8601d5f"), std::make_pair("I915_UUID_L0_SIP_AREA", "21fd6baf-f918-53cc-ba74-f09aaaea2dc0"), std::make_pair("I915_UUID_L0_SBA_AREA", "ec45189d-97d3-58e2-80d1-ab52c72fdcc1"), + std::make_pair("I915_UUID_L0_CONTEXT_ID", "31a8e011-de56-5db1-952b-b241262dc23a"), std::make_pair("L0_ZEBIN_MODULE", "88d347c1-c79b-530a-b68f-e0db7d575e04")}; constexpr auto uuidL0CommandQueueName = "L0_COMMAND_QUEUE"; diff --git a/shared/source/os_interface/linux/drm_memory_manager.cpp b/shared/source/os_interface/linux/drm_memory_manager.cpp index a2983b28fc..828e8c7758 100644 --- a/shared/source/os_interface/linux/drm_memory_manager.cpp +++ b/shared/source/os_interface/linux/drm_memory_manager.cpp @@ -499,7 +499,10 @@ GraphicsAllocation *DrmMemoryManager::allocateGraphicsMemoryWithGpuVa(const Allo } auto allocation = new DrmAllocation(allocationData.rootDeviceIndex, allocationData.type, bo.get(), res, bo->peekAddress(), alignedSize, MemoryPool::System4KBPages); + allocation->storageInfo = allocationData.storageInfo; allocation->setDriverAllocatedCpuPtr(res); + allocation->setOsContext(osContextLinux); + bo.release(); return allocation; diff --git a/shared/source/os_interface/linux/drm_memory_manager_create_multi_host_allocation.cpp b/shared/source/os_interface/linux/drm_memory_manager_create_multi_host_allocation.cpp index a0b0db83ba..e9e36a4dbf 100644 --- a/shared/source/os_interface/linux/drm_memory_manager_create_multi_host_allocation.cpp +++ b/shared/source/os_interface/linux/drm_memory_manager_create_multi_host_allocation.cpp @@ -13,6 +13,7 @@ #include "shared/source/os_interface/linux/drm_allocation.h" #include "shared/source/os_interface/linux/drm_buffer_object.h" #include "shared/source/os_interface/linux/drm_memory_manager.h" +#include "shared/source/os_interface/linux/os_context_linux.h" namespace NEO { @@ -50,6 +51,9 @@ DrmAllocation *DrmMemoryManager::createMultiHostAllocation(const AllocationData allocation->setUncacheable(true); allocation->setDriverAllocatedCpuPtr(cpuBasePointer); + auto osContextLinux = static_cast(allocationData.osContext); + allocation->setOsContext(osContextLinux); + if (addressReserved) { allocation->setReservedAddressRange(reinterpret_cast(gpuAddress), sizePerTile); } diff --git a/shared/test/common/mocks/linux/mock_os_context_linux.h b/shared/test/common/mocks/linux/mock_os_context_linux.h new file mode 100644 index 0000000000..a341bce8b4 --- /dev/null +++ b/shared/test/common/mocks/linux/mock_os_context_linux.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2023 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once +#include "shared/source/os_interface/linux/os_context_linux.h" + +namespace NEO { +class MockOsContextLinux : public OsContextLinux { + public: + using OsContextLinux::drmContextIds; + + MockOsContextLinux(Drm &drm, uint32_t rootDeviceIndex, uint32_t contextId, const EngineDescriptor &engineDescriptor) + : OsContextLinux(drm, rootDeviceIndex, contextId, engineDescriptor) {} +}; +static_assert(sizeof(OsContextLinux) == sizeof(MockOsContextLinux)); + +} // namespace NEO \ No newline at end of file diff --git a/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp index 810d2b369d..deafcc458b 100644 --- a/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_memory_manager_tests.cpp @@ -19,6 +19,7 @@ #include "shared/test/common/mocks/linux/mock_drm_allocation.h" #include "shared/test/common/mocks/linux/mock_drm_command_stream_receiver.h" #include "shared/test/common/mocks/linux/mock_drm_memory_manager.h" +#include "shared/test/common/mocks/linux/mock_os_context_linux.h" #include "shared/test/common/mocks/mock_allocation_properties.h" #include "shared/test/common/mocks/mock_execution_environment.h" #include "shared/test/common/mocks/mock_gfx_partition.h" @@ -3922,6 +3923,143 @@ TEST_F(DrmAllocationTests, givenResourceRegistrationEnabledWhenIsaIsRegisteredTh EXPECT_EQ(static_cast(allocation.storageInfo.subDeviceBitfield.to_ulong()), *data); } +TEST_F(DrmAllocationTests, givenResourceRegistrationEnabledAndSubDeviceBitfieldSetWhenSbaTrackingBufferIsRegisteredThenDeviceContextIdIsPassedAsPayload) { + DrmMockResources drm(*executionEnvironment->rootDeviceEnvironments[0]); + + for (uint32_t i = 3; i < 3 + static_cast(DrmResourceClass::MaxSize); i++) { + drm.classHandles.push_back(i); + } + + drm.registeredClass = DrmResourceClass::MaxSize; + + MockBufferObject bo(&drm, 3, 0, 0, 1); + MockDrmAllocation allocation(AllocationType::DEBUG_SBA_TRACKING_BUFFER, MemoryPool::LocalMemory); + allocation.storageInfo.tileInstanced = false; + allocation.storageInfo.subDeviceBitfield = 0b0010; + allocation.bufferObjects[0] = &bo; + + MockOsContextLinux osContext(drm, 0, 0u, EngineDescriptorHelper::getDefaultDescriptor()); + allocation.setOsContext(&osContext); + + osContext.drmContextIds.clear(); + osContext.drmContextIds.push_back(3u); + osContext.drmContextIds.push_back(5u); + + const auto processId = 0xABCEDF; + uint64_t offlineDumpContextId = static_cast(processId) << 32 | static_cast(5u); + + allocation.registerBOBindExtHandle(&drm); + EXPECT_EQ(2u, bo.bindExtHandles.size()); + + EXPECT_EQ(DrmMockResources::registerResourceReturnHandle, bo.bindExtHandles[0]); + + uint64_t *data = reinterpret_cast(drm.registeredData); + EXPECT_EQ(offlineDumpContextId, *data); + + allocation.freeRegisteredBOBindExtHandles(&drm); + EXPECT_EQ(2u, drm.unregisterCalledCount); +} + +TEST_F(DrmAllocationTests, givenResourceRegistrationEnabledAndSubDeviceBitfieldNotSetWhenSbaTrackingBufferIsRegisteredThenContextIdIsTakenFromDevice0AndPassedAsPayload) { + DrmMockResources drm(*executionEnvironment->rootDeviceEnvironments[0]); + + for (uint32_t i = 3; i < 3 + static_cast(DrmResourceClass::MaxSize); i++) { + drm.classHandles.push_back(i); + } + + drm.registeredClass = DrmResourceClass::MaxSize; + + MockBufferObject bo(&drm, 3, 0, 0, 1); + MockDrmAllocation allocation(AllocationType::DEBUG_SBA_TRACKING_BUFFER, MemoryPool::LocalMemory); + allocation.storageInfo.tileInstanced = false; + allocation.bufferObjects[0] = &bo; + + MockOsContextLinux osContext(drm, 0, 0u, EngineDescriptorHelper::getDefaultDescriptor()); + allocation.setOsContext(&osContext); + + osContext.drmContextIds.clear(); + osContext.drmContextIds.push_back(3u); + osContext.drmContextIds.push_back(5u); + + const auto processId = 0xABCEDF; + uint64_t offlineDumpContextId = static_cast(processId) << 32 | static_cast(3u); + + allocation.registerBOBindExtHandle(&drm); + EXPECT_EQ(2u, bo.bindExtHandles.size()); + + EXPECT_EQ(DrmMockResources::registerResourceReturnHandle, bo.bindExtHandles[0]); + + uint64_t *data = reinterpret_cast(drm.registeredData); + EXPECT_EQ(offlineDumpContextId, *data); + + allocation.freeRegisteredBOBindExtHandles(&drm); + EXPECT_EQ(2u, drm.unregisterCalledCount); +} + +TEST_F(DrmAllocationTests, givenTwoBufferObjectsAndTileInstancedSbaAndSubDeviceBitfieldWhenSbaTrackingBufferIsRegisteredThenContextIdIsTakenFromBufferObjectIndexAndPassedAsPayload) { + DrmMockResources drm(*executionEnvironment->rootDeviceEnvironments[0]); + + for (uint32_t i = 3; i < 3 + static_cast(DrmResourceClass::MaxSize); i++) { + drm.classHandles.push_back(i); + } + + drm.registeredClass = DrmResourceClass::MaxSize; + + MockBufferObject bo0(&drm, 3, 0, 0, 1); + MockBufferObject bo1(&drm, 3, 0, 0, 1); + + MockDrmAllocation allocation(AllocationType::DEBUG_SBA_TRACKING_BUFFER, MemoryPool::LocalMemory); + allocation.storageInfo.subDeviceBitfield = 0b0011; + allocation.storageInfo.tileInstanced = true; + allocation.bufferObjects[0] = &bo0; + allocation.bufferObjects[1] = &bo1; + + MockOsContextLinux osContext(drm, 0, 0u, EngineDescriptorHelper::getDefaultDescriptor()); + allocation.setOsContext(&osContext); + + osContext.drmContextIds.clear(); + osContext.drmContextIds.push_back(3u); + osContext.drmContextIds.push_back(5u); + + const auto processId = 0xABCEDF; + uint64_t offlineDumpContextIdBo1 = static_cast(processId) << 32 | static_cast(5u); + + allocation.registerBOBindExtHandle(&drm); + EXPECT_EQ(2u, bo0.bindExtHandles.size()); + EXPECT_EQ(2u, bo1.bindExtHandles.size()); + + EXPECT_EQ(DrmMockResources::registerResourceReturnHandle, bo0.bindExtHandles[0]); + EXPECT_EQ(DrmMockResources::registerResourceReturnHandle, bo1.bindExtHandles[0]); + + uint64_t *dataBo1 = reinterpret_cast(drm.registeredData); + EXPECT_EQ(offlineDumpContextIdBo1, *dataBo1); + + allocation.freeRegisteredBOBindExtHandles(&drm); + EXPECT_EQ(3u, drm.unregisterCalledCount); +} + +TEST_F(DrmAllocationTests, givenResourceRegistrationEnabledWhenSbaTrackingBufferIsRegisteredWithoutOsContextThenHandleIsNotAddedToBO) { + DrmMockResources drm(*executionEnvironment->rootDeviceEnvironments[0]); + + for (uint32_t i = 3; i < 3 + static_cast(DrmResourceClass::MaxSize); i++) { + drm.classHandles.push_back(i); + } + + drm.registeredClass = DrmResourceClass::MaxSize; + + MockBufferObject bo(&drm, 3, 0, 0, 1); + MockDrmAllocation allocation(AllocationType::DEBUG_SBA_TRACKING_BUFFER, MemoryPool::LocalMemory); + allocation.bufferObjects[0] = &bo; + + allocation.registerBOBindExtHandle(&drm); + EXPECT_EQ(1u, bo.bindExtHandles.size()); + + EXPECT_EQ(DrmMockResources::registerResourceReturnHandle, bo.bindExtHandles[0]); + + allocation.freeRegisteredBOBindExtHandles(&drm); + EXPECT_EQ(1u, drm.unregisterCalledCount); +} + TEST_F(DrmAllocationTests, givenDrmAllocationWhenSetCacheRegionIsCalledForDefaultRegionThenReturnTrue) { DrmMock drm(*executionEnvironment->rootDeviceEnvironments[0]); diff --git a/shared/test/unit_test/os_interface/linux/drm_uuid_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_uuid_tests.cpp index 6f3741198b..251a8e87c4 100644 --- a/shared/test/unit_test/os_interface/linux/drm_uuid_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_uuid_tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2022 Intel Corporation + * Copyright (C) 2020-2023 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -57,6 +57,7 @@ TEST(DrmUuidTest, whenResourceClassIsUsedToIndexClassNamesThenCorrectNamesAreRet EXPECT_STREQ(classNamesToUuid[static_cast(DrmResourceClass::ContextSaveArea)].first, "I915_UUID_L0_SIP_AREA"); EXPECT_STREQ(classNamesToUuid[static_cast(DrmResourceClass::ModuleHeapDebugArea)].first, "I915_UUID_L0_MODULE_AREA"); EXPECT_STREQ(classNamesToUuid[static_cast(DrmResourceClass::SbaTrackingBuffer)].first, "I915_UUID_L0_SBA_AREA"); + EXPECT_STREQ(classNamesToUuid[static_cast(DrmResourceClass::ContextID)].first, "I915_UUID_L0_CONTEXT_ID"); EXPECT_STREQ(classNamesToUuid[static_cast(DrmResourceClass::L0ZebinModule)].first, "L0_ZEBIN_MODULE"); } diff --git a/shared/test/unit_test/os_interface/linux/os_context_linux_tests.cpp b/shared/test/unit_test/os_interface/linux/os_context_linux_tests.cpp index 438345aad3..11e9ddad35 100644 --- a/shared/test/unit_test/os_interface/linux/os_context_linux_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/os_context_linux_tests.cpp @@ -9,6 +9,7 @@ #include "shared/source/os_interface/linux/os_context_linux.h" #include "shared/test/common/helpers/engine_descriptor_helper.h" #include "shared/test/common/libult/linux/drm_mock.h" +#include "shared/test/common/mocks/linux/mock_os_context_linux.h" #include "shared/test/common/mocks/mock_execution_environment.h" #include "shared/test/common/os_interface/linux/device_command_stream_fixture.h" @@ -39,18 +40,10 @@ TEST(OSContextLinux, givenInitializeContextWhenContextCreateIoctlFailsThenContex } TEST(OSContextLinux, givenOsContextLinuxWhenQueryingForOfflineDumpContextIdThenCorrectValueIsReturned) { - class OsContextLinuxMock : public OsContextLinux { - public: - using OsContextLinux::drmContextIds; - - OsContextLinuxMock(Drm &drm, uint32_t rootDeviceIndex, uint32_t contextId, const EngineDescriptor &engineDescriptor) - : OsContextLinux(drm, rootDeviceIndex, contextId, engineDescriptor) {} - }; - MockExecutionEnvironment executionEnvironment; std::unique_ptr mock(new DrmMockCustom(*executionEnvironment.rootDeviceEnvironments[0])); executionEnvironment.rootDeviceEnvironments[0]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*mock.get(), 0u); - OsContextLinuxMock osContext(*mock, 0, 0u, EngineDescriptorHelper::getDefaultDescriptor()); + MockOsContextLinux osContext(*mock, 0, 0u, EngineDescriptorHelper::getDefaultDescriptor()); osContext.drmContextIds.clear(); osContext.drmContextIds.push_back(1u);