fix: Write tail index even for fifo wrap around case
Related-To: NEO-7990 Signed-off-by: Jitendra Sharma <jitendra.sharma@intel.com>
This commit is contained in:
parent
2b48599c38
commit
733ca5ac28
|
@ -1653,24 +1653,19 @@ void DebugSessionImp::getNotStoppedThreads(const std::vector<EuThread::ThreadId>
|
|||
}
|
||||
}
|
||||
|
||||
bool DebugSessionImp::isValidNode(uint64_t vmHandle, uint64_t gpuVa, SIP::fifo_node &node) {
|
||||
ze_result_t 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;
|
||||
return retVal;
|
||||
}
|
||||
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;
|
||||
return ZE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ze_result_t DebugSessionImp::readFifo(uint64_t vmHandle, std::vector<EuThread::ThreadId> &threadsWithAttention) {
|
||||
|
@ -1683,29 +1678,33 @@ ze_result_t DebugSessionImp::readFifo(uint64_t vmHandle, std::vector<EuThread::T
|
|||
|
||||
// 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 offsetTail = (sizeof(SIP::StateSaveArea)) + offsetof(struct SIP::intelgt_state_save_area_V3, fifo_tail);
|
||||
const uint64_t offsetHead = (sizeof(SIP::StateSaveArea)) + offsetof(struct SIP::intelgt_state_save_area_V3, fifo_head);
|
||||
const uint64_t offsetFifoSize = (sizeof(SIP::StateSaveArea)) + offsetof(struct SIP::intelgt_state_save_area_V3, fifo_size);
|
||||
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;
|
||||
std::vector<uint32_t> fifoIndices(3);
|
||||
uint32_t fifoHeadIndex = 0, fifoTailIndex = 0, fifoSize = 0;
|
||||
|
||||
auto retVal = readGpuMemory(vmHandle, reinterpret_cast<char *>(fifoIndices.data()), fifoIndices.size() * sizeof(uint32_t), gpuVa + offsetHead);
|
||||
auto retVal = readGpuMemory(vmHandle, reinterpret_cast<char *>(fifoIndices.data()), fifoIndices.size() * sizeof(uint32_t), gpuVa + offsetFifoSize);
|
||||
if (retVal != ZE_RESULT_SUCCESS) {
|
||||
PRINT_DEBUGGER_ERROR_LOG("Reading FIFO indices failed, error = %d\n", retVal);
|
||||
return retVal;
|
||||
}
|
||||
fifoHeadIndex = fifoIndices[0];
|
||||
fifoTailIndex = fifoIndices[1];
|
||||
fifoSize = fifoIndices[0];
|
||||
fifoHeadIndex = fifoIndices[1];
|
||||
fifoTailIndex = fifoIndices[2];
|
||||
|
||||
if (lastHead != fifoHeadIndex) {
|
||||
drainRetries++;
|
||||
}
|
||||
PRINT_DEBUGGER_FIFO_LOG("fifoHeadIndex: %u fifoTailIndex: %u fifoSize: %u lastHead: %u drainRetries: %u\n",
|
||||
fifoHeadIndex, fifoTailIndex, fifoSize, lastHead, drainRetries);
|
||||
|
||||
while (fifoTailIndex != fifoHeadIndex) {
|
||||
uint32_t readSize = fifoTailIndex < fifoHeadIndex ? fifoHeadIndex - fifoTailIndex : stateSaveAreaHeader->regHeaderV3.fifo_size - fifoTailIndex;
|
||||
uint32_t readSize = fifoTailIndex < fifoHeadIndex ? fifoHeadIndex - fifoTailIndex : fifoSize - fifoTailIndex;
|
||||
std::vector<SIP::fifo_node> nodes(readSize);
|
||||
uint64_t currentFifoOffset = offsetFifo + (sizeof(SIP::fifo_node) * fifoTailIndex);
|
||||
|
||||
|
@ -1715,8 +1714,21 @@ ze_result_t DebugSessionImp::readFifo(uint64_t vmHandle, std::vector<EuThread::T
|
|||
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]));
|
||||
const uint64_t gpuVa = currentFifoOffset + (i * sizeof(SIP::fifo_node));
|
||||
PRINT_DEBUGGER_FIFO_LOG("Validate entry at index %u in SW Fifo:: vmHandle: %" SCNx64
|
||||
" gpuVa: %" SCNx64
|
||||
" valid: %" SCNx8
|
||||
" thread_id: %" SCNx8
|
||||
" eu_id: %" SCNx8
|
||||
" subslice_id: %" SCNx8
|
||||
" slice_id: %" SCNx8
|
||||
"\n",
|
||||
(i + fifoTailIndex), vmHandle, gpuVa, nodes[i].valid, nodes[i].thread_id, nodes[i].eu_id, nodes[i].subslice_id, nodes[i].slice_id);
|
||||
retVal = isValidNode(vmHandle, gpuVa, nodes[i]);
|
||||
if (retVal != ZE_RESULT_SUCCESS) {
|
||||
return retVal;
|
||||
}
|
||||
UNRECOVERABLE_IF(!nodes[i].valid);
|
||||
threadsWithAttention.emplace_back(0, nodes[i].slice_id, nodes[i].subslice_id, nodes[i].eu_id, nodes[i].thread_id);
|
||||
nodes[i].valid = 0;
|
||||
}
|
||||
|
@ -1729,16 +1741,18 @@ ze_result_t DebugSessionImp::readFifo(uint64_t vmHandle, std::vector<EuThread::T
|
|||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
retVal = readGpuMemory(vmHandle, reinterpret_cast<char *>(&lastHead), sizeof(uint32_t), gpuVa + offsetHead);
|
||||
if (retVal != ZE_RESULT_SUCCESS) {
|
||||
PRINT_DEBUGGER_ERROR_LOG("Reading fifo_head failed, error = %d\n", retVal);
|
||||
|
|
|
@ -120,7 +120,7 @@ struct DebugSessionImp : DebugSession {
|
|||
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);
|
||||
MOCKABLE_VIRTUAL ze_result_t 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;
|
||||
|
|
|
@ -1911,6 +1911,32 @@ TEST_F(DebugSessionTestSwFifoFixture, GivenSwFifoWhenReadingSwFifoThenFifoIsCorr
|
|||
}
|
||||
}
|
||||
|
||||
TEST_F(DebugSessionTestSwFifoFixture, GivenSwFifoWithHeadIndexAtZeroWhenReadingSwFifoThenFifoIsCorrectlyReadAndDrained) {
|
||||
EXPECT_FALSE(session->stateSaveAreaHeader.empty());
|
||||
stateSaveAreaHeaderPtr = reinterpret_cast<NEO::StateSaveAreaHeader *>(session->stateSaveAreaHeader.data());
|
||||
stateSaveAreaHeaderPtr->regHeaderV3.fifo_head = 0;
|
||||
|
||||
std::vector<EuThread::ThreadId> threadsWithAttention;
|
||||
session->readFifo(0, threadsWithAttention);
|
||||
|
||||
std::vector<SIP::fifo_node> readFifoForValidation(stateSaveAreaHeaderPtr->regHeaderV3.fifo_size);
|
||||
session->readGpuMemory(0, reinterpret_cast<char *>(readFifoForValidation.data()), readFifoForValidation.size() * sizeof(SIP::fifo_node),
|
||||
reinterpret_cast<uint64_t>(session->stateSaveAreaHeader.data()) + offsetFifo);
|
||||
for (size_t i = fifoTail; i < readFifoForValidation.size(); i++) {
|
||||
EXPECT_EQ(readFifoForValidation[i].valid, 0);
|
||||
}
|
||||
EXPECT_EQ(stateSaveAreaHeaderPtr->regHeaderV3.fifo_head, stateSaveAreaHeaderPtr->regHeaderV3.fifo_tail);
|
||||
|
||||
EXPECT_EQ(threadsWithAttention.size(), fifoVecFromTail.size());
|
||||
size_t index = 0;
|
||||
for (; index < fifoVecFromTail.size(); index++) {
|
||||
EXPECT_EQ(threadsWithAttention[index].slice, fifoVecFromTail[index].slice_id);
|
||||
EXPECT_EQ(threadsWithAttention[index].subslice, fifoVecFromTail[index].subslice_id);
|
||||
EXPECT_EQ(threadsWithAttention[index].eu, fifoVecFromTail[index].eu_id);
|
||||
EXPECT_EQ(threadsWithAttention[index].thread, fifoVecFromTail[index].thread_id);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DebugSessionTestSwFifoFixture, GivenSwFifoWhenWriteGpuMemoryFailsWhileInValidatingNodeDuringFifoReadThenErrorReturned) {
|
||||
EXPECT_FALSE(session->stateSaveAreaHeader.empty());
|
||||
session->writeMemoryResult = ZE_RESULT_ERROR_UNKNOWN;
|
||||
|
@ -1968,22 +1994,14 @@ TEST(DebugSessionTest, GivenSwFifoWhenStateSaveAreaVersionIsLessThanThreeDuringF
|
|||
EXPECT_EQ(ZE_RESULT_SUCCESS, session->readFifo(0, threadsWithAttention));
|
||||
}
|
||||
|
||||
TEST_F(DebugSessionTest, GivenSwFifoNodeWhenCheckingIsValidNodeThenAfterCheckingValidityOfNodeTrueOrFalseReturned) {
|
||||
zet_debug_config_t config = {};
|
||||
config.pid = 0x1234;
|
||||
auto hwInfo = *NEO::defaultHwInfo.get();
|
||||
NEO::MockDevice *neoDevice(NEO::MockDevice::createWithNewExecutionEnvironment<NEO::MockDevice>(&hwInfo, 0));
|
||||
MockDeviceImp deviceImp(neoDevice, neoDevice->getExecutionEnvironment());
|
||||
auto session = std::make_unique<MockDebugSession>(config, &deviceImp);
|
||||
|
||||
SIP::fifo_node node1 = {0, 1, 1, 0, 0};
|
||||
EXPECT_FALSE(session->isValidNode(0, 0, node1));
|
||||
|
||||
SIP::fifo_node node2 = {1, 1, 1, 0, 0};
|
||||
EXPECT_TRUE(session->isValidNode(0, 0, node2));
|
||||
TEST_F(DebugSessionTestSwFifoFixture, GivenSwFifoWhenReadingSwFifoAndIsValidNodeFailsThenFifoReadReturnsError) {
|
||||
EXPECT_FALSE(session->stateSaveAreaHeader.empty());
|
||||
std::vector<EuThread::ThreadId> threadsWithAttention;
|
||||
session->isValidNodeResult = ZE_RESULT_ERROR_NOT_AVAILABLE;
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, session->readFifo(0, threadsWithAttention));
|
||||
}
|
||||
|
||||
TEST_F(DebugSessionTest, GivenInvalidSwFifoNodeWhenCheckingIsValidNodeAndOnReadingMemoryAgainNodeTurnsValidThenTrueReturned) {
|
||||
TEST_F(DebugSessionTest, GivenInvalidSwFifoNodeWhenCheckingIsValidNodeAndOnReadingMemoryAgainNodeTurnsValidThenSuccessReturned) {
|
||||
zet_debug_config_t config = {};
|
||||
config.pid = 0x1234;
|
||||
auto hwInfo = *NEO::defaultHwInfo.get();
|
||||
|
@ -1993,16 +2011,18 @@ TEST_F(DebugSessionTest, GivenInvalidSwFifoNodeWhenCheckingIsValidNodeAndOnReadi
|
|||
|
||||
// Declare node whose valid field is 0
|
||||
SIP::fifo_node invalidNode = {0, 1, 1, 0, 0};
|
||||
EXPECT_FALSE(session->isValidNode(0, reinterpret_cast<uint64_t>(session->readMemoryBuffer.data()), invalidNode));
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, session->isValidNode(0, reinterpret_cast<uint64_t>(session->readMemoryBuffer.data()), invalidNode));
|
||||
EXPECT_FALSE(invalidNode.valid);
|
||||
|
||||
SIP::fifo_node correctedNode = {1, 1, 1, 0, 0};
|
||||
session->readMemoryBuffer.resize(sizeof(SIP::fifo_node));
|
||||
memcpy_s(session->readMemoryBuffer.data(), session->readMemoryBuffer.size(), reinterpret_cast<void *>(&correctedNode), sizeof(SIP::fifo_node));
|
||||
|
||||
EXPECT_TRUE(session->isValidNode(0, reinterpret_cast<uint64_t>(session->readMemoryBuffer.data()), invalidNode));
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, session->isValidNode(0, reinterpret_cast<uint64_t>(session->readMemoryBuffer.data()), invalidNode));
|
||||
EXPECT_TRUE(invalidNode.valid);
|
||||
}
|
||||
|
||||
TEST_F(DebugSessionTest, GivenInvalidSwFifoNodeWhenCheckingIsValidNodeAndOnReadingMemoryAgainReadMemoryFailsThenFalseReturned) {
|
||||
TEST_F(DebugSessionTest, GivenInvalidSwFifoNodeWhenCheckingIsValidNodeAndOnReadingMemoryAgainReadMemoryFailsThenErrorReturned) {
|
||||
zet_debug_config_t config = {};
|
||||
config.pid = 0x1234;
|
||||
auto hwInfo = *NEO::defaultHwInfo.get();
|
||||
|
@ -2013,7 +2033,7 @@ TEST_F(DebugSessionTest, GivenInvalidSwFifoNodeWhenCheckingIsValidNodeAndOnReadi
|
|||
// Declare node whose valid field is 0
|
||||
SIP::fifo_node invalidNode = {0, 1, 1, 0, 0};
|
||||
session->readMemoryResult = ZE_RESULT_ERROR_UNKNOWN;
|
||||
EXPECT_FALSE(session->isValidNode(0, reinterpret_cast<uint64_t>(session->readMemoryBuffer.data()), invalidNode));
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, session->isValidNode(0, reinterpret_cast<uint64_t>(session->readMemoryBuffer.data()), invalidNode));
|
||||
}
|
||||
|
||||
TEST_F(DebugSessionTest, givenTssMagicCorruptedWhenStateSaveAreIsReadThenHeaderIsNotSet) {
|
||||
|
|
|
@ -250,6 +250,14 @@ struct MockDebugSession : public L0::DebugSessionImp {
|
|||
return ZE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ze_result_t isValidNode(uint64_t vmHandle, uint64_t gpuVa, SIP::fifo_node &node) override {
|
||||
if (isValidNodeResult != ZE_RESULT_SUCCESS) {
|
||||
return isValidNodeResult;
|
||||
} else {
|
||||
return DebugSessionImp::isValidNode(vmHandle, gpuVa, node);
|
||||
}
|
||||
}
|
||||
|
||||
ze_result_t readRegistersImp(EuThread::ThreadId thread, uint32_t type, uint32_t start, uint32_t count, void *pRegisterValues) override {
|
||||
readRegistersCallCount++;
|
||||
readRegistersReg = type;
|
||||
|
@ -535,6 +543,7 @@ struct MockDebugSession : public L0::DebugSessionImp {
|
|||
ze_result_t writeMemoryResult = ZE_RESULT_SUCCESS;
|
||||
ze_result_t writeRegistersResult = ZE_RESULT_FORCE_UINT32;
|
||||
ze_result_t readThreadScratchRegistersResult = ZE_RESULT_FORCE_UINT32;
|
||||
ze_result_t isValidNodeResult = ZE_RESULT_SUCCESS;
|
||||
|
||||
uint32_t readStateSaveAreaHeaderCalled = 0;
|
||||
uint32_t readRegistersCallCount = 0;
|
||||
|
|
|
@ -105,6 +105,7 @@ struct DebugVariables { // NOLINT(clang-analyzer
|
|||
constexpr static int32_t LOG_ERROR{1 << 1}; // NOLINT(readability-identifier-naming)
|
||||
constexpr static int32_t LOG_THREADS{1 << 2}; // NOLINT(readability-identifier-naming)
|
||||
constexpr static int32_t LOG_MEM{1 << 3}; // NOLINT(readability-identifier-naming)
|
||||
constexpr static int32_t LOG_FIFO{1 << 4}; // NOLINT(readability-identifier-naming)
|
||||
constexpr static int32_t DUMP_ELF{1 << 10}; // NOLINT(readability-identifier-naming)
|
||||
constexpr static int32_t DUMP_TO_FILE{1 << 16}; // NOLINT(readability-identifier-naming)
|
||||
};
|
||||
|
@ -220,6 +221,11 @@ class DurationLog {
|
|||
PRINT_DEBUGGER_LOG(stdout, "\nINFO: " STR, __VA_ARGS__) \
|
||||
}
|
||||
|
||||
#define PRINT_DEBUGGER_FIFO_LOG(STR, ...) \
|
||||
if (NEO::debugManager.flags.DebuggerLogBitmask.get() & NEO::DebugVariables::DEBUGGER_LOG_BITMASK::LOG_FIFO) { \
|
||||
PRINT_DEBUGGER_LOG(stdout, "\nFIFO ACCESS: " STR, __VA_ARGS__) \
|
||||
}
|
||||
|
||||
template <DebugFunctionalityLevel debugLevel>
|
||||
const char *DebugSettingsManager<debugLevel>::settingsDumpFileName = "igdrcl_dumped.config";
|
||||
}; // namespace NEO
|
||||
|
|
Loading…
Reference in New Issue