diff --git a/shared/source/command_container/cmdcontainer.cpp b/shared/source/command_container/cmdcontainer.cpp index 0f489d9198..995d2ca173 100644 --- a/shared/source/command_container/cmdcontainer.cpp +++ b/shared/source/command_container/cmdcontainer.cpp @@ -591,4 +591,22 @@ size_t CommandContainer::getHeapSize(HeapType heapType) { return HeapSize::getDefaultHeapSize(defaultHeapSize); } +void *CommandContainer::findCpuBaseForCmdBufferAddress(void *cmdBufferAddress) { + uintptr_t cmdBufferAddressValue = reinterpret_cast(cmdBufferAddress); + uintptr_t cpuBaseValue = reinterpret_cast(commandStream->getCpuBase()); + if ((cpuBaseValue <= cmdBufferAddressValue) && + ((cpuBaseValue + commandStream->getMaxAvailableSpace()) > cmdBufferAddressValue)) { + return reinterpret_cast(cpuBaseValue); + } + // last cmd buffer allocation is assisgned to commandStream, no need to check it + for (size_t i = 0; i < cmdBufferAllocations.size() - 1; i++) { + cpuBaseValue = reinterpret_cast(cmdBufferAllocations[i]->getUnderlyingBuffer()); + if ((cpuBaseValue <= cmdBufferAddressValue) && + ((cpuBaseValue + getMaxUsableSpace()) > cmdBufferAddressValue)) { + return reinterpret_cast(cpuBaseValue); + } + } + return nullptr; +} + } // namespace NEO diff --git a/shared/source/command_container/cmdcontainer.h b/shared/source/command_container/cmdcontainer.h index 5aced082e1..a4250e8141 100644 --- a/shared/source/command_container/cmdcontainer.h +++ b/shared/source/command_container/cmdcontainer.h @@ -202,6 +202,8 @@ class CommandContainer : public NonCopyableOrMovableClass { } void endAlignedPrimaryBuffer(); + void *findCpuBaseForCmdBufferAddress(void *cmdBufferAddress); + protected: size_t getAlignedCmdBufferSize() const; size_t getMaxUsableSpace() const { diff --git a/shared/test/unit_test/command_container/command_container_tests.cpp b/shared/test/unit_test/command_container/command_container_tests.cpp index ac6b9787b5..ad1d5d5370 100644 --- a/shared/test/unit_test/command_container/command_container_tests.cpp +++ b/shared/test/unit_test/command_container/command_container_tests.cpp @@ -33,6 +33,7 @@ using CommandContainerTest = Test; class MyMockCommandContainer : public CommandContainer { public: using CommandContainer::allocationIndirectHeaps; + using CommandContainer::cmdBufferAllocations; using CommandContainer::defaultSshSize; using CommandContainer::dirtyHeaps; using CommandContainer::getAlignedCmdBufferSize; @@ -1986,3 +1987,45 @@ TEST_F(CommandContainerTest, givenHeaplessCmdContainerWhenResetContainerThenNoHe cmdContainer.reset(); EXPECT_EQ(0u, deallocationList.size()); } + +TEST_F(CommandContainerTest, givenInitializedContainerWhenSearchedAddressIsWithinCommandStreamThenReturnCommandStreamCpuBase) { + MyMockCommandContainer cmdContainer; + + auto status = cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, false, false); + EXPECT_EQ(CommandContainer::ErrorCode::success, status); + + void *cmdBuffer = ptrOffset(cmdContainer.getCommandStream()->getCpuBase(), 0x100); + void *cpuBase = cmdContainer.findCpuBaseForCmdBufferAddress(cmdBuffer); + EXPECT_EQ(cmdContainer.getCommandStream()->getCpuBase(), cpuBase); +} + +TEST_F(CommandContainerTest, givenInitializedContainerWithTwoCommandBuffersWhenSearchedAddressIsWithinOldCommandBufferThenReturnOldCommandBufferCpuBase) { + MyMockCommandContainer cmdContainer; + + auto status = cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, false, false); + EXPECT_EQ(CommandContainer::ErrorCode::success, status); + + void *expectedCpuBase = cmdContainer.getCommandStream()->getCpuBase(); + void *cmdBuffer = ptrOffset(expectedCpuBase, 0x200); + cmdContainer.allocateNextCommandBuffer(); + EXPECT_NE(expectedCpuBase, cmdContainer.getCommandStream()->getCpuBase()); + + void *cpuBase = cmdContainer.findCpuBaseForCmdBufferAddress(cmdBuffer); + EXPECT_EQ(expectedCpuBase, cpuBase); +} + +TEST_F(CommandContainerTest, givenInitializedContainerWhenSearchedAddressIsOutsideCommandStreamThenReturnNullptr) { + MyMockCommandContainer cmdContainer; + + auto status = cmdContainer.initialize(pDevice, nullptr, HeapSize::defaultHeapSize, false, false); + EXPECT_EQ(CommandContainer::ErrorCode::success, status); + cmdContainer.allocateNextCommandBuffer(); + + void *cmdBuffer = reinterpret_cast(0x1); + void *cpuBase = cmdContainer.findCpuBaseForCmdBufferAddress(cmdBuffer); + EXPECT_EQ(nullptr, cpuBase); + + cmdBuffer = reinterpret_cast(std::numeric_limits::max()); + cpuBase = cmdContainer.findCpuBaseForCmdBufferAddress(cmdBuffer); + EXPECT_EQ(nullptr, cpuBase); +}