feature: Add SW FIFO implementation

Related-To: NEO-7990
Signed-off-by: Jitendra Sharma <jitendra.sharma@intel.com>
This commit is contained in:
Jitendra Sharma
2024-08-19 21:18:39 +00:00
committed by Compute-Runtime-Automation
parent 4404d0c6b8
commit 6df6e4bbb0
12 changed files with 296 additions and 4 deletions

View File

@@ -1638,4 +1638,92 @@ void DebugSessionImp::getNotStoppedThreads(const std::vector<EuThread::ThreadId>
}
}
bool DebugSessionImp::isValidNode(uint64_t vmHandle, uint64_t gpuVa, SIP::fifo_node &node) {
constexpr uint32_t failsafeTimeoutMax = 100, failsafeTimeoutWait = 50;
uint32_t timeCount = 0;
while (!node.valid && (timeCount < failsafeTimeoutMax)) {
auto retVal = readGpuMemory(vmHandle, reinterpret_cast<char *>(&node), sizeof(SIP::fifo_node), gpuVa);
if (retVal != ZE_RESULT_SUCCESS) {
PRINT_DEBUGGER_ERROR_LOG("Reading FIFO failed, error = %d\n", retVal);
return false;
}
NEO::sleep(std::chrono::milliseconds(failsafeTimeoutWait));
timeCount += failsafeTimeoutWait;
}
if (!node.valid) {
PRINT_DEBUGGER_ERROR_LOG("%S", "Invalid entry in SW FIFO\n");
return false;
}
return true;
}
ze_result_t DebugSessionImp::readFifo(uint64_t vmHandle, std::vector<EuThread::ThreadId> &threadsWithAttention) {
auto stateSaveAreaHeader = getStateSaveAreaHeader();
if (stateSaveAreaHeader->versionHeader.version.major < 3) {
return ZE_RESULT_SUCCESS;
}
auto gpuVa = getContextStateSaveAreaGpuVa(vmHandle);
// Drain the fifo
uint32_t drainRetries = 2, lastHead = ~0u;
uint64_t offsetTail = (sizeof(SIP::StateSaveArea)) + offsetof(struct SIP::intelgt_state_save_area_V3, fifo_tail);
uint64_t offsetHead = (sizeof(SIP::StateSaveArea)) + offsetof(struct SIP::intelgt_state_save_area_V3, fifo_head);
const uint64_t offsetFifo = gpuVa + (stateSaveAreaHeader->versionHeader.size * 8) + stateSaveAreaHeader->regHeaderV3.fifo_offset;
while (drainRetries--) {
constexpr uint32_t failsafeTimeoutWait = 50;
std::vector<uint32_t> fifoIndices(2);
uint32_t fifoHeadIndex = 0, fifoTailIndex = 0;
readGpuMemory(vmHandle, reinterpret_cast<char *>(fifoIndices.data()), fifoIndices.size() * sizeof(uint32_t), gpuVa + offsetHead);
fifoHeadIndex = fifoIndices[0];
fifoTailIndex = fifoIndices[1];
if (lastHead != fifoHeadIndex) {
drainRetries++;
}
while (fifoTailIndex != fifoHeadIndex) {
uint32_t readSize = fifoTailIndex < fifoHeadIndex ? fifoHeadIndex - fifoTailIndex : stateSaveAreaHeader->regHeaderV3.fifo_size - fifoTailIndex;
std::vector<SIP::fifo_node> nodes(readSize);
uint64_t currentFifoOffset = offsetFifo + (sizeof(SIP::fifo_node) * fifoTailIndex);
auto retVal = readGpuMemory(vmHandle, reinterpret_cast<char *>(nodes.data()), readSize * sizeof(SIP::fifo_node), currentFifoOffset);
if (retVal != ZE_RESULT_SUCCESS) {
PRINT_DEBUGGER_ERROR_LOG("Reading FIFO failed, error = %d\n", retVal);
return retVal;
}
for (uint32_t i = 0; i < readSize; i++) {
PRINT_DEBUGGER_INFO_LOG("Validate entry at index %u in SW Fifo\n", (i + fifoTailIndex));
UNRECOVERABLE_IF(!isValidNode(vmHandle, currentFifoOffset + (i * sizeof(SIP::fifo_node)), nodes[i]));
threadsWithAttention.emplace_back(0, nodes[i].slice_id, nodes[i].subslice_id, nodes[i].eu_id, nodes[i].thread_id);
nodes[i].valid = 0;
}
retVal = writeGpuMemory(vmHandle, reinterpret_cast<char *>(nodes.data()), readSize * sizeof(SIP::fifo_node), currentFifoOffset);
if (retVal != ZE_RESULT_SUCCESS) {
PRINT_DEBUGGER_ERROR_LOG("Writing FIFO failed, error = %d\n", retVal);
return retVal;
}
if (fifoTailIndex < fifoHeadIndex) {
// then we read to the head and are done
fifoTailIndex = fifoHeadIndex;
retVal = writeGpuMemory(vmHandle, reinterpret_cast<char *>(&fifoTailIndex), sizeof(uint32_t), gpuVa + offsetTail);
if (retVal != ZE_RESULT_SUCCESS) {
PRINT_DEBUGGER_ERROR_LOG("Writing FIFO failed, error = %d\n", retVal);
return retVal;
}
} else {
// wrap around
fifoTailIndex = 0;
}
}
lastHead = stateSaveAreaHeader->regHeaderV3.fifo_head;
NEO::sleep(std::chrono::milliseconds(failsafeTimeoutWait));
}
return ZE_RESULT_SUCCESS;
}
} // namespace L0

View File

@@ -119,6 +119,8 @@ struct DebugSessionImp : DebugSession {
const NEO::StateSaveAreaHeader *getStateSaveAreaHeader();
void validateAndSetStateSaveAreaHeader(uint64_t vmHandle, uint64_t gpuVa);
virtual void readStateSaveAreaHeader(){};
MOCKABLE_VIRTUAL ze_result_t readFifo(uint64_t vmHandle, std::vector<EuThread::ThreadId> &threadsWithAttention);
MOCKABLE_VIRTUAL bool isValidNode(uint64_t vmHandle, uint64_t gpuVa, SIP::fifo_node &node);
virtual uint64_t getContextStateSaveAreaGpuVa(uint64_t memoryHandle) = 0;
virtual size_t getContextStateSaveAreaSize(uint64_t memoryHandle) = 0;

View File

@@ -24,6 +24,7 @@ if(UNIX)
target_sources(${L0_STATIC_LIB_NAME}
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/xe/debug_session.cpp
${CMAKE_CURRENT_SOURCE_DIR}/xe/${BRANCH_DIR_SUFFIX}handle_event_helper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/xe/debug_session.h
)
endif()

View File

@@ -205,7 +205,7 @@ struct DebugSessionLinux : DebugSessionImp {
apiEventCondition.notify_all();
}
void updateStoppedThreadsAndCheckTriggerEvents(AttentionEventFields &attention, uint32_t tileIndex, std::vector<EuThread::ThreadId> &threadsWithAttention);
MOCKABLE_VIRTUAL void updateStoppedThreadsAndCheckTriggerEvents(AttentionEventFields &attention, uint32_t tileIndex, std::vector<EuThread::ThreadId> &threadsWithAttention);
virtual void updateContextAndLrcHandlesForThreadsWithAttention(EuThread::ThreadId threadId, AttentionEventFields &attention) = 0;
virtual uint64_t getVmHandleFromClientAndlrcHandle(uint64_t clientHandle, uint64_t lrcHandle) = 0;
virtual std::unique_lock<std::mutex> getThreadStateMutexForTileSession(uint32_t tileIndex) = 0;

View File

@@ -126,7 +126,7 @@ void DebugSessionLinuxXe::readInternalEventsAsync() {
if (result == ZE_RESULT_SUCCESS) {
std::lock_guard<std::mutex> lock(internalEventThreadMutex);
if (event->type == DRM_XE_EUDEBUG_EVENT_EU_ATTENTION) {
if (eventTypeIsAttention(event->type)) {
newestAttSeqNo.store(event->seqno);
}
@@ -343,7 +343,7 @@ void DebugSessionLinuxXe::handleEvent(drm_xe_eudebug_event *event) {
} break;
default:
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: UNHANDLED %u flags = %u len = %lu\n", (uint16_t)event->type, (uint16_t)event->flags, (uint32_t)event->len);
additionalEvents(event);
break;
}
}

View File

@@ -136,6 +136,8 @@ struct DebugSessionLinuxXe : DebugSessionLinux {
std::vector<std::unique_ptr<uint64_t[]>> pendingVmBindEvents;
bool checkAllEventsCollected();
MOCKABLE_VIRTUAL void handleEvent(drm_xe_eudebug_event *event);
void additionalEvents(drm_xe_eudebug_event *event);
MOCKABLE_VIRTUAL bool eventTypeIsAttention(uint16_t eventType);
void readInternalEventsAsync() override;
std::atomic<bool> detached{false};

View File

@@ -0,0 +1,22 @@
/*
* Copyright (C) 2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/debug_settings/debug_settings_manager.h"
#include "level_zero/tools/source/debug/linux/xe/debug_session.h"
namespace L0 {
void DebugSessionLinuxXe::additionalEvents(drm_xe_eudebug_event *event) {
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: UNHANDLED %u flags = %u len = %lu\n", (uint16_t)event->type, (uint16_t)event->flags, (uint32_t)event->len);
}
bool DebugSessionLinuxXe::eventTypeIsAttention(uint16_t eventType) {
return (eventType == DRM_XE_EUDEBUG_EVENT_EU_ATTENTION);
}
} // namespace L0