L0Debug - Notify cmdQueue create for subdevices

- PROCESS ENTRY triggered for first cmdQ created

Related-To: NEO-5784

Signed-off-by: Mateusz Hoppe <mateusz.hoppe@intel.com>
This commit is contained in:
Mateusz Hoppe
2022-07-19 18:05:13 +00:00
committed by Compute-Runtime-Automation
parent 547dd59272
commit ebcb3faad2
16 changed files with 244 additions and 51 deletions

View File

@@ -63,7 +63,7 @@ ze_result_t CommandQueueImp::initialize(bool copyOnly, bool isInternal) {
partitionCount = csr->getActivePartitions();
}
if (NEO::Debugger::isDebugEnabled(internalUsage) && device->getL0Debugger()) {
device->getL0Debugger()->notifyCommandQueueCreated();
device->getL0Debugger()->notifyCommandQueueCreated(device->getNEODevice());
}
}
return returnValue;

View File

@@ -61,7 +61,7 @@ ze_result_t CommandQueueHw<gfxCoreFamily>::destroy() {
}
buffers.destroy(this->getDevice());
if (NEO::Debugger::isDebugEnabled(internalUsage) && device->getL0Debugger()) {
device->getL0Debugger()->notifyCommandQueueDestroyed();
device->getL0Debugger()->notifyCommandQueueDestroyed(device->getNEODevice());
}
delete this;
return ZE_RESULT_SUCCESS;

View File

@@ -14,6 +14,7 @@
#include "level_zero/core/source/cmdlist/cmdlist.h"
#include "level_zero/core/source/device/device.h"
#include "level_zero/core/test/unit_tests/fixtures/device_fixture.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"
@@ -26,13 +27,13 @@ namespace L0 {
namespace ult {
struct L0DebuggerLinuxFixture {
void SetUp() { // NOLINT(readability-identifier-naming)
void SetUp(HardwareInfo *hwInfo = nullptr) {
auto executionEnvironment = new NEO::ExecutionEnvironment();
auto mockBuiltIns = new MockBuiltins();
auto mockBuiltIns = new NEO::MockBuiltins();
executionEnvironment->prepareRootDeviceEnvironments(1);
executionEnvironment->setDebuggingEnabled();
executionEnvironment->rootDeviceEnvironments[0]->builtins.reset(mockBuiltIns);
executionEnvironment->rootDeviceEnvironments[0]->setHwInfo(defaultHwInfo.get());
executionEnvironment->rootDeviceEnvironments[0]->setHwInfo(hwInfo ? hwInfo : defaultHwInfo.get());
executionEnvironment->initializeMemoryManager();
auto osInterface = new OSInterface();
drmMock = new DrmMockResources(*executionEnvironment->rootDeviceEnvironments[0]);
@@ -50,8 +51,7 @@ struct L0DebuggerLinuxFixture {
device = driverHandle->devices[0];
}
void TearDown() { // NOLINT(readability-identifier-naming)
}
void TearDown(){};
std::unique_ptr<Mock<L0::DriverHandleImp>> driverHandle;
NEO::MockDevice *neoDevice = nullptr;
@@ -59,7 +59,39 @@ struct L0DebuggerLinuxFixture {
DrmMockResources *drmMock = nullptr;
};
struct L0DebuggerLinuxMultitileFixture : public L0DebuggerLinuxFixture {
void SetUp() {
DebugManager.flags.CreateMultipleRootDevices.set(1);
constexpr auto numSubDevices = 2u;
DebugManager.flags.CreateMultipleSubDevices.set(2);
hwInfo = *defaultHwInfo;
hwInfo.gtSystemInfo.MultiTileArchInfo.IsValid = 1;
hwInfo.gtSystemInfo.MultiTileArchInfo.TileCount = numSubDevices;
hwInfo.gtSystemInfo.MultiTileArchInfo.Tile0 = 1;
hwInfo.gtSystemInfo.MultiTileArchInfo.Tile1 = 1;
hwInfo.gtSystemInfo.MultiTileArchInfo.TileMask = 3;
L0DebuggerLinuxFixture::SetUp(&hwInfo);
subDevice0 = neoDevice->getSubDevice(0)->getSpecializedDevice<Device>();
subDevice1 = neoDevice->getSubDevice(1)->getSpecializedDevice<Device>();
}
void TearDown() {
L0DebuggerLinuxFixture::TearDown();
}
DebugManagerStateRestore restorer;
HardwareInfo hwInfo;
L0::Device *subDevice0 = nullptr;
L0::Device *subDevice1 = nullptr;
};
using L0DebuggerLinuxTest = Test<L0DebuggerLinuxFixture>;
using L0DebuggerLinuxMultitileTest = Test<L0DebuggerLinuxMultitileFixture>;
TEST_F(L0DebuggerLinuxTest, givenProgramDebuggingEnabledWhenDriverHandleIsCreatedThenItAllocatesL0Debugger) {
EXPECT_NE(nullptr, neoDevice->getDebugger());
@@ -292,5 +324,40 @@ HWTEST_F(L0DebuggerLinuxTest, givenDebuggingEnabledWhenImmCommandListsCreatedAnd
EXPECT_EQ(2u, debuggerL0Hw->commandQueueDestroyedCount);
}
HWTEST_F(L0DebuggerLinuxMultitileTest, givenDebuggingEnabledWhenCommandQueuesCreatedThenDebuggerIsNotified) {
auto debuggerL0Hw = static_cast<MockDebuggerL0Hw<FamilyType> *>(device->getL0Debugger());
drmMock->ioctlCallsCount = 0;
neoDevice->getDefaultEngine().commandStreamReceiver->getOsContext().ensureContextInitialized();
EXPECT_EQ(2u, debuggerL0Hw->uuidL0CommandQueueHandle.size());
ze_command_queue_desc_t queueDesc = {};
ze_result_t returnValue;
auto commandQueue1 = CommandQueue::create(productFamily, subDevice0, neoDevice->getDefaultEngine().commandStreamReceiver, &queueDesc, false, false, returnValue);
EXPECT_EQ(1u, drmMock->ioctlCallsCount);
EXPECT_EQ(1u, debuggerL0Hw->commandQueueCreatedCount);
EXPECT_EQ(ZE_RESULT_SUCCESS, returnValue);
auto commandQueue2 = CommandQueue::create(productFamily, subDevice1, neoDevice->getDefaultEngine().commandStreamReceiver, &queueDesc, false, false, returnValue);
EXPECT_EQ(2u, debuggerL0Hw->commandQueueCreatedCount);
EXPECT_EQ(ZE_RESULT_SUCCESS, returnValue);
for (uint32_t index = 0; index < neoDevice->getNumSubDevices(); index++) {
EXPECT_NE(0u, debuggerL0Hw->uuidL0CommandQueueHandle[index]);
}
commandQueue1->destroy();
EXPECT_EQ(1u, debuggerL0Hw->commandQueueDestroyedCount);
commandQueue2->destroy();
EXPECT_EQ(2u, drmMock->unregisterCalledCount);
EXPECT_EQ(2u, debuggerL0Hw->commandQueueDestroyedCount);
for (uint32_t index = 0; index < neoDevice->getNumSubDevices(); index++) {
EXPECT_EQ(0u, debuggerL0Hw->uuidL0CommandQueueHandle[index]);
}
}
} // namespace ult
} // namespace L0

View File

@@ -459,10 +459,20 @@ void DebugSessionLinux::handleEvent(prelim_drm_i915_debug_event *event) {
clientHandleToConnection[uuid->client_handle]->uuidToModule.erase(uuid->handle);
}
if (destroy && (uuidL0CommandQueueHandle == uuid->handle) && (clientHandle == uuid->client_handle)) {
zet_debug_event_t debugEvent = {};
debugEvent.type = ZET_DEBUG_EVENT_TYPE_PROCESS_EXIT;
pushApiEvent(debugEvent, nullptr);
if (destroy && (clientHandle == uuid->client_handle)) {
for (const auto &uuidToDevice : uuidL0CommandQueueHandleToDevice) {
if (uuidToDevice.first == uuid->handle) {
uuidL0CommandQueueHandleToDevice.erase(uuidToDevice.first);
if (uuidL0CommandQueueHandleToDevice.size() == 0) {
zet_debug_event_t debugEvent = {};
debugEvent.type = ZET_DEBUG_EVENT_TYPE_PROCESS_EXIT;
pushApiEvent(debugEvent, nullptr);
}
break;
}
}
break;
}
@@ -485,10 +495,20 @@ void DebugSessionLinux::handleEvent(prelim_drm_i915_debug_event *event) {
if (uuidString == NEO::uuidL0CommandQueueHash) {
if ((clientHandle == invalidClientHandle) || (clientHandle == uuid->client_handle)) {
clientHandle = uuid->client_handle;
uuidL0CommandQueueHandle = uuid->handle;
zet_debug_event_t debugEvent = {};
debugEvent.type = ZET_DEBUG_EVENT_TYPE_PROCESS_ENTRY;
pushApiEvent(debugEvent, nullptr);
uint32_t deviceIndex = 0;
if (readUuid.payload_size == sizeof(NEO::DebuggerL0::CommandQueueNotification)) {
auto notification = reinterpret_cast<NEO::DebuggerL0::CommandQueueNotification *>(payload.get());
deviceIndex = notification->subDeviceIndex;
UNRECOVERABLE_IF(notification->subDeviceIndex >= notification->subDeviceCount);
}
if (uuidL0CommandQueueHandleToDevice.size() == 0) {
zet_debug_event_t debugEvent = {};
debugEvent.type = ZET_DEBUG_EVENT_TYPE_PROCESS_ENTRY;
pushApiEvent(debugEvent, nullptr);
}
uuidL0CommandQueueHandleToDevice[uuid->handle] = deviceIndex;
}
}

View File

@@ -248,7 +248,7 @@ struct DebugSessionLinux : DebugSessionImp {
uint64_t clientHandle = invalidClientHandle;
uint64_t clientHandleClosed = invalidClientHandle;
uint64_t uuidL0CommandQueueHandle = invalidClientHandle;
std::unordered_map<uint64_t, uint32_t> uuidL0CommandQueueHandleToDevice;
uint64_t euControlInterruptSeqno[NEO::EngineLimits::maxHandleCount];
std::unordered_map<uint64_t, std::unique_ptr<ClientConnection>> clientHandleToConnection;

View File

@@ -296,7 +296,7 @@ struct MockDebugSessionLinux : public L0::DebugSessionLinux {
using L0::DebugSessionLinux::ThreadControlCmd;
using L0::DebugSessionLinux::typeToRegsetDesc;
using L0::DebugSessionLinux::typeToRegsetFlags;
using L0::DebugSessionLinux::uuidL0CommandQueueHandle;
using L0::DebugSessionLinux::uuidL0CommandQueueHandleToDevice;
using L0::DebugSessionLinux::writeGpuMemory;
MockDebugSessionLinux(const zet_debug_config_t &config, L0::Device *device, int debugFd) : DebugSessionLinux(config, device, debugFd) {
@@ -1152,6 +1152,9 @@ TEST_F(DebugApiLinuxTest, GivenUuidCommandQueueCreatedHandledThenProcessEntryEve
EXPECT_EQ(1u, session->apiEvents.size());
EXPECT_EQ(MockDebugSessionLinux::mockClientHandle, session->clientHandle);
EXPECT_EQ(3, handler->ioctlCalled);
EXPECT_EQ(0u, session->uuidL0CommandQueueHandleToDevice[2]);
auto event = session->apiEvents.front();
EXPECT_EQ(ZET_DEBUG_EVENT_TYPE_PROCESS_ENTRY, event.type);
@@ -1159,11 +1162,86 @@ TEST_F(DebugApiLinuxTest, GivenUuidCommandQueueCreatedHandledThenProcessEntryEve
uuid.client_handle = MockDebugSessionLinux::mockClientHandle;
handler->returnUuid = &readUuid;
session->handleEvent(&uuid.base);
EXPECT_EQ(2u, session->apiEvents.size());
EXPECT_EQ(1u, session->apiEvents.size());
EXPECT_EQ(MockDebugSessionLinux::mockClientHandle, session->clientHandle);
EXPECT_EQ(4, handler->ioctlCalled);
event = session->apiEvents.front();
}
TEST_F(DebugApiLinuxTest, GivenUuidCommandQueueWhenQueuesOnToSubdevicesCreatedAndDestroyedThenProcessEntryAndExitEventIsGeneratedOnce) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinux>(config, device, 10);
ASSERT_NE(nullptr, session);
session->clientHandle = MockDebugSessionLinux::mockClientHandle;
prelim_drm_i915_debug_event_uuid uuid = {};
uuid.base.type = PRELIM_DRM_I915_DEBUG_EVENT_UUID;
uuid.base.flags = PRELIM_DRM_I915_DEBUG_EVENT_CREATE;
uuid.base.size = sizeof(prelim_drm_i915_debug_event_uuid);
uuid.client_handle = MockDebugSessionLinux::mockClientHandle;
uuid.handle = 2;
uuid.payload_size = sizeof(NEO::DebuggerL0::CommandQueueNotification);
auto uuidHash = NEO::uuidL0CommandQueueHash;
prelim_drm_i915_debug_read_uuid readUuid = {};
memcpy(readUuid.uuid, uuidHash, strlen(uuidHash));
NEO::DebuggerL0::CommandQueueNotification notification;
notification.subDeviceCount = 2;
notification.subDeviceIndex = 1;
readUuid.payload_ptr = reinterpret_cast<uint64_t>(&notification);
readUuid.payload_size = sizeof(NEO::DebuggerL0::CommandQueueNotification);
readUuid.handle = uuid.handle;
auto handler = new MockIoctlHandler;
session->ioctlHandler.reset(handler);
handler->returnUuid = &readUuid;
// Handle UUID create for commandQueue on subdevice 1
session->handleEvent(&uuid.base);
EXPECT_EQ(1, handler->ioctlCalled);
EXPECT_EQ(1u, session->apiEvents.size());
auto event = session->apiEvents.front();
EXPECT_EQ(ZET_DEBUG_EVENT_TYPE_PROCESS_ENTRY, event.type);
EXPECT_EQ(1u, session->uuidL0CommandQueueHandleToDevice.size());
notification.subDeviceCount = 2;
notification.subDeviceIndex = 0;
uuid.handle = 3;
handler->returnUuid = &readUuid;
// Handle UUID create for commandQueue on subdevice 0
session->handleEvent(&uuid.base);
EXPECT_EQ(2, handler->ioctlCalled);
EXPECT_EQ(1u, session->apiEvents.size());
EXPECT_EQ(2u, session->uuidL0CommandQueueHandleToDevice.size());
EXPECT_EQ(1u, session->uuidL0CommandQueueHandleToDevice[2]);
EXPECT_EQ(0u, session->uuidL0CommandQueueHandleToDevice[3]);
// Handle UUID destroy for commandQueue on subdevice 0
uuid.base.flags = PRELIM_DRM_I915_DEBUG_EVENT_DESTROY;
session->handleEvent(&uuid.base);
EXPECT_EQ(1u, session->uuidL0CommandQueueHandleToDevice.size());
EXPECT_EQ(1u, session->apiEvents.size());
// Handle UUID destroy with invalid uuid handle
uuid.handle = 300;
session->handleEvent(&uuid.base);
EXPECT_EQ(1u, session->uuidL0CommandQueueHandleToDevice.size());
// Handle UUID destroy for commandQueue on subdevice 1
uuid.handle = 2;
session->handleEvent(&uuid.base);
EXPECT_EQ(0u, session->uuidL0CommandQueueHandleToDevice.size());
EXPECT_EQ(2u, session->apiEvents.size());
session->apiEvents.pop();
event = session->apiEvents.front();
EXPECT_EQ(ZET_DEBUG_EVENT_TYPE_PROCESS_EXIT, event.type);
}
TEST_F(DebugApiLinuxTest, GivenCommandQueueDestroyedWhenHandlingEventThenExitEventIsGenerated) {
@@ -1173,7 +1251,8 @@ TEST_F(DebugApiLinuxTest, GivenCommandQueueDestroyedWhenHandlingEventThenExitEve
auto session = std::make_unique<MockDebugSessionLinux>(config, device, 10);
ASSERT_NE(nullptr, session);
session->clientHandle = DebugSessionLinux::invalidHandle;
session->uuidL0CommandQueueHandle = 5;
const uint64_t validUuidCmdQHandle = 5u;
session->uuidL0CommandQueueHandleToDevice[validUuidCmdQHandle] = 0;
prelim_drm_i915_debug_event_uuid uuid = {};
uuid.base.type = PRELIM_DRM_I915_DEBUG_EVENT_UUID;
@@ -1193,7 +1272,7 @@ TEST_F(DebugApiLinuxTest, GivenCommandQueueDestroyedWhenHandlingEventThenExitEve
session->handleEvent(&uuid.base);
EXPECT_EQ(0u, session->apiEvents.size());
uuid.handle = session->uuidL0CommandQueueHandle;
uuid.handle = validUuidCmdQHandle;
session->handleEvent(&uuid.base);
EXPECT_EQ(0u, session->apiEvents.size());