L0 Debugger Win - read SBA tracking buffer address

MMIO will store SBA tracking buffer address for current context.
This change helps in extracting this address and use to read SBA virtual
register.

Related-To: NEO-6765

Signed-off-by: Jitendra Sharma <jitendra.sharma@intel.com>
This commit is contained in:
Jitendra Sharma
2022-06-15 17:27:17 +00:00
committed by Compute-Runtime-Automation
parent 4ece30528c
commit c86c518bc4
4 changed files with 124 additions and 4 deletions

View File

@@ -7,6 +7,8 @@
#include "level_zero/tools/source/debug/windows/debug_session.h"
#include "shared/source/helpers/register_offsets.h"
namespace L0 {
DebugSession *createDebugSessionHelper(const zet_debug_config_t &config, Device *device, int debugFd);
@@ -456,8 +458,39 @@ bool DebugSessionWindows::readModuleDebugArea() {
return false;
}
ze_result_t DebugSessionWindows::readSbaBuffer(EuThread::ThreadId, NEO::SbaTrackedAddresses &sbaBuffer) {
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
ze_result_t DebugSessionWindows::readSbaBuffer(EuThread::ThreadId threadId, NEO::SbaTrackedAddresses &sbaBuffer) {
uint64_t gpuVa = 0;
getSbaBufferGpuVa(gpuVa);
if (gpuVa == 0) {
return ZE_RESULT_ERROR_UNKNOWN;
}
uint64_t memoryHandle = DebugSessionWindows::invalidHandle;
memoryHandle = allThreads[threadId]->getMemoryHandle();
if (memoryHandle == EuThread::invalidHandle) {
return ZE_RESULT_ERROR_NOT_AVAILABLE;
}
return readGpuMemory(memoryHandle, reinterpret_cast<char *>(&sbaBuffer), sizeof(sbaBuffer), gpuVa);
}
void DebugSessionWindows::getSbaBufferGpuVa(uint64_t &gpuVa) {
KM_ESCAPE_INFO escapeInfo = {0};
escapeInfo.KmEuDbgL0EscapeInfo.EscapeActionType = DBGUMD_ACTION_READ_MMIO;
escapeInfo.KmEuDbgL0EscapeInfo.MmioReadParams.MmioOffset = CS_GPR_R15;
escapeInfo.KmEuDbgL0EscapeInfo.MmioReadParams.RegisterOutBufferPtr = reinterpret_cast<uint64_t>(&gpuVa);
auto status = runEscape(escapeInfo);
if (STATUS_SUCCESS != status) {
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_READ_MMIO: Escape Failed - Status: %d", status);
return;
}
if (DBGUMD_RETURN_ESCAPE_SUCCESS != escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus) {
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_READ_MMIO: Failed - EscapeReturnStatus: %d\n", escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
return;
}
PRINT_DEBUGGER_INFO_LOG("DBGUMD_ACTION_READ_MMIO: SUCCESS - gpuVa: 0x%ullx\n", gpuVa);
return;
}
} // namespace L0

View File

@@ -64,8 +64,9 @@ struct DebugSessionWindows : DebugSessionImp {
ThreadHelper asyncThread;
std::mutex asyncThreadMutex;
MOCKABLE_VIRTUAL void getSbaBufferGpuVa(uint64_t &gpuVa);
NTSTATUS runEscape(KM_ESCAPE_INFO &escapeInfo);
MOCKABLE_VIRTUAL NTSTATUS runEscape(KM_ESCAPE_INFO &escapeInfo);
bool moduleDebugAreaCaptured = false;
uint32_t processId = 0;

View File

@@ -22,6 +22,7 @@ struct MockDebugSessionWindows : DebugSessionWindows {
using DebugSessionWindows::closeAsyncThread;
using DebugSessionWindows::debugHandle;
using DebugSessionWindows::ElfRange;
using DebugSessionWindows::getSbaBufferGpuVa;
using DebugSessionWindows::initialize;
using DebugSessionWindows::invalidHandle;
using DebugSessionWindows::moduleDebugAreaCaptured;
@@ -29,6 +30,8 @@ struct MockDebugSessionWindows : DebugSessionWindows {
using DebugSessionWindows::readAllocationDebugData;
using DebugSessionWindows::readAndHandleEvent;
using DebugSessionWindows::readGpuMemory;
using DebugSessionWindows::readSbaBuffer;
using DebugSessionWindows::runEscape;
using DebugSessionWindows::startAsyncThread;
using DebugSessionWindows::wddm;
using DebugSessionWindows::writeGpuMemory;
@@ -50,6 +53,18 @@ struct MockDebugSessionWindows : DebugSessionWindows {
return DebugSessionWindows::readAndHandleEvent(timeoutMs);
}
NTSTATUS runEscape(KM_ESCAPE_INFO &escapeInfo) override {
if (shouldEscapeReturnStatusNotSuccess) {
escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus = DBGUMD_RETURN_DEBUGGER_ATTACH_DEVICE_BUSY;
return STATUS_SUCCESS;
}
if (shouldEscapeCallFail) {
return STATUS_WAIT_1;
}
return L0::DebugSessionWindows::runEscape(escapeInfo);
}
void ensureThreadStopped(ze_device_thread_t thread, uint64_t context) {
auto threadId = convertToThreadId(thread);
if (allThreads.find(threadId) == allThreads.end()) {
@@ -61,6 +76,8 @@ struct MockDebugSessionWindows : DebugSessionWindows {
ze_result_t resultInitialize = ZE_RESULT_FORCE_UINT32;
ze_result_t resultReadAndHandleEvent = ZE_RESULT_FORCE_UINT32;
static constexpr uint64_t mockDebugHandle = 1;
bool shouldEscapeReturnStatusNotSuccess = false;
bool shouldEscapeCallFail = false;
};
struct DebugApiWindowsFixture : public DeviceFixture {
@@ -80,6 +97,68 @@ struct DebugApiWindowsFixture : public DeviceFixture {
using DebugApiWindowsTest = Test<DebugApiWindowsFixture>;
TEST_F(DebugApiWindowsTest, GivenReadOfGpuVaFailDueToEscapeCallFailureWhenTryingToReadSbaThenErrorIsReported) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
session->shouldEscapeCallFail = true;
ze_device_thread_t thread{0, 0, 0, 0};
SbaTrackedAddresses sbaBuffer;
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, session->readSbaBuffer(session->convertToThreadId(thread), sbaBuffer));
}
TEST_F(DebugApiWindowsTest, GivenReadOfGpuVaFailDueToEscapeCallReturnsSuccessButEscapeReturnStatusIsNotSuccessWhenReadSbaBufferThenErrorIsReported) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
session->shouldEscapeReturnStatusNotSuccess = true;
ze_device_thread_t thread{0, 0, 0, 0};
SbaTrackedAddresses sbaBuffer;
EXPECT_EQ(ZE_RESULT_ERROR_UNKNOWN, session->readSbaBuffer(session->convertToThreadId(thread), sbaBuffer));
}
TEST_F(DebugApiWindowsTest, GivenSbaBufferGpuVaAvailableWhenReadingSbaBufferThenSuccessIsReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
ze_device_thread_t thread;
thread.slice = 1;
thread.subslice = 1;
thread.eu = 1;
thread.thread = 1;
session->ensureThreadStopped(thread, 0x12345);
SbaTrackedAddresses sbaBuffer;
session->wddm = mockWddm;
session->allContexts.insert(0x12345);
EXPECT_EQ(ZE_RESULT_SUCCESS, session->readSbaBuffer(session->convertToThreadId(thread), sbaBuffer));
EXPECT_EQ(sbaBuffer.Version, 0xaa);
EXPECT_EQ(sbaBuffer.BindlessSamplerStateBaseAddress, 0xaaaaaaaaaaaaaaaa);
}
TEST_F(DebugApiWindowsTest, GivenEscapeCallToReadMMIOReturnsSuccessWhenReadingSbaBufferGpuVaThenValidGpuVaIsObtained) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
session->wddm = mockWddm;
uint64_t gpuVa = 0;
session->getSbaBufferGpuVa(gpuVa);
EXPECT_EQ(mockWddm->mockGpuVa, gpuVa);
}
TEST_F(DebugApiWindowsTest, GivenNoMemoryHandleWhenReadSbaBufferCalledThenErrorIsReturned) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
ze_device_thread_t thread{0, 0, 0, 0};
SbaTrackedAddresses sbaBuffer;
session->wddm = mockWddm;
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, session->readSbaBuffer(session->convertToThreadId(thread), sbaBuffer));
}
TEST_F(DebugApiWindowsTest, givenDebugAttachIsNotAvailableWhenGetDebugPropertiesCalledThenNoFlagIsReturned) {
zet_device_debug_properties_t debugProperties = {};
debugProperties.flags = ZET_DEVICE_DEBUG_PROPERTY_FLAG_FORCE_UINT32;