From 60d6505932c48bf1c9d718d6d887050c160e7d7d Mon Sep 17 00:00:00 2001 From: Igor Venevtsev Date: Thu, 10 Feb 2022 11:13:59 +0000 Subject: [PATCH] L0 debugger - reports process ENTER/EXIT events for zeCommandQueues - PROCESS_ENTRY - triggered by first zeCommandQueueCreate() - PROCESS_EXIT - triggered by last zeCommandQueueDestroy() Resolves: NEO-6503 Signed-off-by: Igor Venevtsev --- level_zero/core/source/cmdqueue/cmdqueue.cpp | 3 +++ .../core/source/cmdqueue/cmdqueue_hw.inl | 3 +++ level_zero/core/source/debugger/debugger_l0.h | 6 ++++- .../debugger/linux/debugger_l0_linux.cpp | 19 ++++++++++++++ .../debugger/windows/debugger_l0_windows.cpp | 6 +++++ .../test/unit_tests/mocks/mock_l0_debugger.h | 13 ++++++++++ .../debugger/linux/test_l0_debugger_linux.cpp | 26 +++++++++++++++++++ .../os_interface/linux/drm_debug_tests.cpp | 17 ++++++++++-- .../source/os_interface/linux/drm_debug.cpp | 4 ++- shared/source/os_interface/linux/drm_neo.h | 3 +++ shared/test/common/libult/linux/drm_mock.h | 9 +++++++ 11 files changed, 105 insertions(+), 4 deletions(-) diff --git a/level_zero/core/source/cmdqueue/cmdqueue.cpp b/level_zero/core/source/cmdqueue/cmdqueue.cpp index bdf945b081..ad85e80534 100644 --- a/level_zero/core/source/cmdqueue/cmdqueue.cpp +++ b/level_zero/core/source/cmdqueue/cmdqueue.cpp @@ -57,6 +57,9 @@ ze_result_t CommandQueueImp::initialize(bool copyOnly, bool isInternal) { if (!isInternal) { partitionCount = csr->getActivePartitions(); } + if (NEO::Debugger::isDebugEnabled(internalUsage) && device->getL0Debugger()) { + device->getL0Debugger()->notifyCommandQueueCreated(); + } } return returnValue; } diff --git a/level_zero/core/source/cmdqueue/cmdqueue_hw.inl b/level_zero/core/source/cmdqueue/cmdqueue_hw.inl index 0fdc101c31..e9163b6fa9 100644 --- a/level_zero/core/source/cmdqueue/cmdqueue_hw.inl +++ b/level_zero/core/source/cmdqueue/cmdqueue_hw.inl @@ -56,6 +56,9 @@ ze_result_t CommandQueueHw::destroy() { commandStream = nullptr; } buffers.destroy(this->getDevice()); + if (NEO::Debugger::isDebugEnabled(internalUsage) && device->getL0Debugger()) { + device->getL0Debugger()->notifyCommandQueueDestroyed(); + } delete this; return ZE_RESULT_SUCCESS; } diff --git a/level_zero/core/source/debugger/debugger_l0.h b/level_zero/core/source/debugger/debugger_l0.h index 6c830daf27..7b4b19e762 100644 --- a/level_zero/core/source/debugger/debugger_l0.h +++ b/level_zero/core/source/debugger/debugger_l0.h @@ -86,6 +86,8 @@ class DebuggerL0 : public NEO::Debugger, NEO::NonCopyableOrMovableClass { void captureStateBaseAddress(NEO::CommandContainer &container, SbaAddresses sba) override; void printTrackedAddresses(uint32_t contextId); MOCKABLE_VIRTUAL void registerElf(NEO::DebugData *debugData, NEO::GraphicsAllocation *isaAllocation); + MOCKABLE_VIRTUAL void notifyCommandQueueCreated(); + MOCKABLE_VIRTUAL void notifyCommandQueueDestroyed(); virtual size_t getSbaTrackingCommandsSize(size_t trackedAddressCount) = 0; virtual void programSbaTrackingCommands(NEO::LinearStream &cmdStream, const SbaAddresses &sba) = 0; @@ -108,6 +110,8 @@ class DebuggerL0 : public NEO::Debugger, NEO::NonCopyableOrMovableClass { std::unordered_map perContextSbaAllocations; NEO::AddressRange sbaTrackingGpuVa; NEO::GraphicsAllocation *moduleDebugArea = nullptr; + std::atomic commandQueueCount = 0u; + uint32_t uuidL0CommandQueueHandle = 0; }; using DebugerL0CreateFn = DebuggerL0 *(*)(NEO::Device *device); @@ -132,4 +136,4 @@ struct DebuggerL0PopulateFactory { } }; -} // namespace L0 \ No newline at end of file +} // namespace L0 diff --git a/level_zero/core/source/debugger/linux/debugger_l0_linux.cpp b/level_zero/core/source/debugger/linux/debugger_l0_linux.cpp index 83da5f425e..32f9d6628f 100644 --- a/level_zero/core/source/debugger/linux/debugger_l0_linux.cpp +++ b/level_zero/core/source/debugger/linux/debugger_l0_linux.cpp @@ -58,4 +58,23 @@ bool DebuggerL0::removeZebinModule(uint32_t moduleHandle) { drm->unregisterResource(moduleHandle); return true; } + +void DebuggerL0::notifyCommandQueueCreated() { + if (device->getRootDeviceEnvironment().osInterface.get() != nullptr) { + if (++commandQueueCount == 1) { + auto drm = device->getRootDeviceEnvironment().osInterface->getDriverModel()->as(); + uuidL0CommandQueueHandle = drm->notifyFirstCommandQueueCreated(); + } + } +} + +void DebuggerL0::notifyCommandQueueDestroyed() { + if (device->getRootDeviceEnvironment().osInterface.get() != nullptr) { + if (--commandQueueCount == 0) { + auto drm = device->getRootDeviceEnvironment().osInterface->getDriverModel()->as(); + drm->notifyLastCommandQueueDestroyed(uuidL0CommandQueueHandle); + } + } +} + } // namespace L0 diff --git a/level_zero/core/source/debugger/windows/debugger_l0_windows.cpp b/level_zero/core/source/debugger/windows/debugger_l0_windows.cpp index cabc7005bd..28f80e4477 100644 --- a/level_zero/core/source/debugger/windows/debugger_l0_windows.cpp +++ b/level_zero/core/source/debugger/windows/debugger_l0_windows.cpp @@ -27,4 +27,10 @@ bool DebuggerL0::removeZebinModule(uint32_t moduleHandle) { return false; } +void DebuggerL0::notifyCommandQueueCreated() { +} + +void DebuggerL0::notifyCommandQueueDestroyed() { +} + } // namespace L0 diff --git a/level_zero/core/test/unit_tests/mocks/mock_l0_debugger.h b/level_zero/core/test/unit_tests/mocks/mock_l0_debugger.h index d0f7cbe0b8..2a0f24aa02 100644 --- a/level_zero/core/test/unit_tests/mocks/mock_l0_debugger.h +++ b/level_zero/core/test/unit_tests/mocks/mock_l0_debugger.h @@ -57,15 +57,28 @@ class MockDebuggerL0Hw : public L0::DebuggerL0Hw { } return L0::DebuggerL0Hw::attachZebinModuleToSegmentAllocations(allocs, moduleHandle); } + bool removeZebinModule(uint32_t moduleHandle) override { removedZebinModuleHandle = moduleHandle; return L0::DebuggerL0Hw::removeZebinModule(moduleHandle); } + void notifyCommandQueueCreated() override { + commandQueueCreatedCount++; + L0::DebuggerL0Hw::notifyCommandQueueCreated(); + } + + void notifyCommandQueueDestroyed() override { + commandQueueDestroyedCount++; + L0::DebuggerL0Hw::notifyCommandQueueDestroyed(); + } + uint32_t captureStateBaseAddressCount = 0; uint32_t programSbaTrackingCommandsCount = 0; uint32_t getSbaTrackingCommandsSizeCount = 0; uint32_t registerElfCount = 0; + uint32_t commandQueueCreatedCount = 0; + uint32_t commandQueueDestroyedCount = 0; const char *lastReceivedElf = nullptr; uint32_t segmentCountWithAttachedModuleHandle = 0; diff --git a/level_zero/core/test/unit_tests/sources/debugger/linux/test_l0_debugger_linux.cpp b/level_zero/core/test/unit_tests/sources/debugger/linux/test_l0_debugger_linux.cpp index f359ccb835..b6d6b15bd9 100644 --- a/level_zero/core/test/unit_tests/sources/debugger/linux/test_l0_debugger_linux.cpp +++ b/level_zero/core/test/unit_tests/sources/debugger/linux/test_l0_debugger_linux.cpp @@ -12,6 +12,7 @@ #include "shared/test/common/mocks/linux/mock_drm_allocation.h" #include "shared/test/common/test_macros/test.h" +#include "level_zero/core/test/unit_tests/mocks/mock_cmdqueue.h" #include "level_zero/core/test/unit_tests/sources/debugger/l0_debugger_fixture.h" #include @@ -219,5 +220,30 @@ TEST_F(L0DebuggerLinuxTest, givenModuleHandleWhenRemoveZebinModuleIsCalledThenHa EXPECT_EQ(20u, drmMock->unregisteredHandle); } +HWTEST_F(L0DebuggerLinuxTest, givenDebuggingEnabledAndCommandQueuesAreCreatedAndDestroyedThanDebuggerL0IsNotified) { + auto debuggerL0Hw = static_cast *>(device->getL0Debugger()); + + neoDevice->getDefaultEngine().commandStreamReceiver->getOsContext().ensureContextInitialized(); + drmMock->ioctlCallsCount = 0; + + ze_command_queue_desc_t queueDesc = {}; + ze_result_t returnValue; + auto commandQueue1 = CommandQueue::create(productFamily, device, neoDevice->getDefaultEngine().commandStreamReceiver, &queueDesc, false, false, returnValue); + EXPECT_EQ(1u, drmMock->ioctlCallsCount); + EXPECT_EQ(1u, debuggerL0Hw->commandQueueCreatedCount); + + auto commandQueue2 = CommandQueue::create(productFamily, device, neoDevice->getDefaultEngine().commandStreamReceiver, &queueDesc, false, false, returnValue); + EXPECT_EQ(1u, drmMock->ioctlCallsCount); + EXPECT_EQ(2u, debuggerL0Hw->commandQueueCreatedCount); + + commandQueue1->destroy(); + EXPECT_EQ(1u, drmMock->ioctlCallsCount); + EXPECT_EQ(1u, debuggerL0Hw->commandQueueDestroyedCount); + + commandQueue2->destroy(); + EXPECT_EQ(1u, drmMock->unregisterCalledCount); + EXPECT_EQ(2u, debuggerL0Hw->commandQueueDestroyedCount); +} + } // namespace ult } // namespace L0 diff --git a/opencl/test/unit_test/os_interface/linux/drm_debug_tests.cpp b/opencl/test/unit_test/os_interface/linux/drm_debug_tests.cpp index 9337da90c3..05b069f2e7 100644 --- a/opencl/test/unit_test/os_interface/linux/drm_debug_tests.cpp +++ b/opencl/test/unit_test/os_interface/linux/drm_debug_tests.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2021 Intel Corporation + * Copyright (C) 2020-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -43,7 +43,7 @@ TEST(DrmTest, whenRegisterIsaCookieCalledThenImplementationIsEmpty) { EXPECT_EQ(0u, drmMock.ioctlCallsCount); } -TEST(DrmTest, WhenCheckingContextDebugSupportThenNoIoctlIsCalled) { +TEST(DrmTest, whenCheckingContextDebugSupportThenNoIoctlIsCalled) { auto executionEnvironment = std::make_unique(); executionEnvironment->prepareRootDeviceEnvironments(1); DrmMock drmMock(*executionEnvironment->rootDeviceEnvironments[0]); @@ -52,3 +52,16 @@ TEST(DrmTest, WhenCheckingContextDebugSupportThenNoIoctlIsCalled) { EXPECT_EQ(0u, drmMock.ioctlCallsCount); } + +TEST(DrmTest, whenNotifyCommandQueueCreateDestroyAreCalledThenImplementationsAreEmpty) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + DrmMock drmMock(*executionEnvironment->rootDeviceEnvironments[0]); + + auto handle = drmMock.notifyFirstCommandQueueCreated(); + EXPECT_EQ(0u, handle); + EXPECT_EQ(0u, drmMock.ioctlCallsCount); + + drmMock.notifyLastCommandQueueDestroyed(0); + EXPECT_EQ(0u, drmMock.ioctlCallsCount); +} diff --git a/shared/source/os_interface/linux/drm_debug.cpp b/shared/source/os_interface/linux/drm_debug.cpp index 20db5914fb..654f4db43f 100644 --- a/shared/source/os_interface/linux/drm_debug.cpp +++ b/shared/source/os_interface/linux/drm_debug.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020-2021 Intel Corporation + * Copyright (C) 2020-2022 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -45,5 +45,7 @@ std::string Drm::generateElfUUID(const void *data) { void Drm::checkContextDebugSupport() {} void Drm::setContextDebugFlag(uint32_t drmContextId) {} +uint32_t Drm::notifyFirstCommandQueueCreated() { return 0; } +void Drm::notifyLastCommandQueueDestroyed(uint32_t handle) {} } // namespace NEO diff --git a/shared/source/os_interface/linux/drm_neo.h b/shared/source/os_interface/linux/drm_neo.h index 12b2953605..1cba4cc687 100644 --- a/shared/source/os_interface/linux/drm_neo.h +++ b/shared/source/os_interface/linux/drm_neo.h @@ -249,6 +249,9 @@ class Drm : public DriverModel { MOCKABLE_VIRTUAL bool completionFenceSupport(); + MOCKABLE_VIRTUAL uint32_t notifyFirstCommandQueueCreated(); + MOCKABLE_VIRTUAL void notifyLastCommandQueueDestroyed(uint32_t handle); + protected: Drm(std::unique_ptr &&hwDeviceIdIn, RootDeviceEnvironment &rootDeviceEnvironment); diff --git a/shared/test/common/libult/linux/drm_mock.h b/shared/test/common/libult/linux/drm_mock.h index c7e4bafe14..0c3b44e1d1 100644 --- a/shared/test/common/libult/linux/drm_mock.h +++ b/shared/test/common/libult/linux/drm_mock.h @@ -288,6 +288,15 @@ class DrmMockResources : public DrmMock { return bindAvailable; } + uint32_t notifyFirstCommandQueueCreated() override { + ioctlCallsCount++; + return 4; + } + + void notifyLastCommandQueueDestroyed(uint32_t handle) override { + unregisterResource(handle); + } + static const uint32_t registerResourceReturnHandle; uint32_t unregisteredHandle = 0;