mirror of
https://github.com/intel/compute-runtime.git
synced 2026-01-03 14:55:24 +08:00
L0 Windows Debugger - Implement GPU mem read/write
Signed-off-by: Yates, Brandon <brandon.yates@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
153811998f
commit
60b88806d5
@@ -70,7 +70,7 @@ ze_result_t DebugSessionWindows::initialize() {
|
||||
}
|
||||
|
||||
bool DebugSessionWindows::closeConnection() {
|
||||
if (debugHandle == 0) {
|
||||
if (debugHandle == invalidHandle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -303,12 +303,94 @@ ze_result_t DebugSessionWindows::readEvent(uint64_t timeout, zet_debug_event_t *
|
||||
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
|
||||
ze_result_t DebugSessionWindows::readMemory(ze_device_thread_t thread, const zet_debug_memory_space_desc_t *desc, size_t size, void *buffer) {
|
||||
ze_result_t DebugSessionWindows::readElfSpace(const zet_debug_memory_space_desc_t *desc, size_t size, void *buffer) {
|
||||
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
|
||||
bool DebugSessionWindows::isVAElf(const zet_debug_memory_space_desc_t *desc, size_t size) {
|
||||
std::unique_lock<std::mutex> lock(asyncThreadMutex);
|
||||
for (auto elf : allElfs) {
|
||||
if (desc->address >= elf.startVA && desc->address <= elf.endVA) {
|
||||
if (desc->address + size > elf.endVA) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ze_result_t DebugSessionWindows::readMemory(ze_device_thread_t thread, const zet_debug_memory_space_desc_t *desc, size_t size, void *buffer) {
|
||||
|
||||
if (debugHandle == invalidHandle) {
|
||||
return ZE_RESULT_ERROR_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if (!isValidGpuAddress(desc->address)) {
|
||||
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ze_result_t status = ZE_RESULT_ERROR_UNINITIALIZED;
|
||||
status = sanityMemAccessThreadCheck(thread, desc);
|
||||
if (status != ZE_RESULT_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (isVAElf(desc, size)) {
|
||||
return readElfSpace(desc, size, buffer);
|
||||
}
|
||||
|
||||
uint64_t memoryHandle = DebugSessionWindows::invalidHandle;
|
||||
|
||||
if (DebugSession::isThreadAll(thread)) {
|
||||
std::unique_lock<std::mutex> lock(asyncThreadMutex);
|
||||
if (allContexts.empty()) {
|
||||
return ZE_RESULT_ERROR_UNINITIALIZED;
|
||||
}
|
||||
memoryHandle = *allContexts.begin();
|
||||
} else {
|
||||
auto threadId = convertToThreadId(thread);
|
||||
memoryHandle = allThreads[threadId]->getMemoryHandle();
|
||||
if (memoryHandle == EuThread::invalidHandle) {
|
||||
return ZE_RESULT_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
return readGpuMemory(memoryHandle, static_cast<char *>(buffer), size, desc->address);
|
||||
}
|
||||
|
||||
ze_result_t DebugSessionWindows::writeMemory(ze_device_thread_t thread, const zet_debug_memory_space_desc_t *desc, size_t size, const void *buffer) {
|
||||
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
|
||||
|
||||
if (debugHandle == invalidHandle) {
|
||||
return ZE_RESULT_ERROR_UNINITIALIZED;
|
||||
}
|
||||
|
||||
if (!isValidGpuAddress(desc->address)) {
|
||||
return ZE_RESULT_ERROR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
ze_result_t status = ZE_RESULT_ERROR_UNINITIALIZED;
|
||||
status = sanityMemAccessThreadCheck(thread, desc);
|
||||
if (status != ZE_RESULT_SUCCESS) {
|
||||
return status;
|
||||
}
|
||||
|
||||
uint64_t memoryHandle = DebugSessionWindows::invalidHandle;
|
||||
|
||||
if (DebugSession::isThreadAll(thread)) {
|
||||
std::unique_lock<std::mutex> lock(asyncThreadMutex);
|
||||
if (allContexts.empty()) {
|
||||
return ZE_RESULT_ERROR_UNINITIALIZED;
|
||||
}
|
||||
memoryHandle = *allContexts.begin();
|
||||
} else {
|
||||
auto threadId = convertToThreadId(thread);
|
||||
memoryHandle = allThreads[threadId]->getMemoryHandle();
|
||||
if (memoryHandle == EuThread::invalidHandle) {
|
||||
return ZE_RESULT_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
return writeGpuMemory(memoryHandle, static_cast<const char *>(buffer), size, desc->address);
|
||||
}
|
||||
|
||||
ze_result_t DebugSessionWindows::acknowledgeEvent(const zet_debug_event_t *event) {
|
||||
@@ -324,11 +406,43 @@ ze_result_t DebugSessionWindows::interruptImp(uint32_t deviceIndex) {
|
||||
}
|
||||
|
||||
ze_result_t DebugSessionWindows::readGpuMemory(uint64_t memoryHandle, char *output, size_t size, uint64_t gpuVa) {
|
||||
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
|
||||
|
||||
auto gmmHelper = connectedDevice->getNEODevice()->getGmmHelper();
|
||||
gpuVa = gmmHelper->decanonize(gpuVa);
|
||||
|
||||
KM_ESCAPE_INFO escapeInfo = {0};
|
||||
escapeInfo.KmEuDbgL0EscapeInfo.EscapeActionType = DBGUMD_ACTION_READ_GFX_MEMORY;
|
||||
escapeInfo.KmEuDbgL0EscapeInfo.ReadGfxMemoryParams.hContextHandle = memoryHandle;
|
||||
escapeInfo.KmEuDbgL0EscapeInfo.ReadGfxMemoryParams.GpuVirtualAddr = gpuVa;
|
||||
escapeInfo.KmEuDbgL0EscapeInfo.ReadGfxMemoryParams.MemoryBufferSize = static_cast<uint32_t>(size);
|
||||
escapeInfo.KmEuDbgL0EscapeInfo.ReadGfxMemoryParams.MemoryBufferPtr = reinterpret_cast<uint64_t>(output);
|
||||
|
||||
auto status = runEscape(escapeInfo);
|
||||
if (STATUS_SUCCESS != status || DBGUMD_RETURN_ESCAPE_SUCCESS != escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus) {
|
||||
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_READ_GFX_MEMORY: Failed - ProcessId: %d Status: %d EscapeReturnStatus: %d\n", processId, status, escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
|
||||
return DebugSessionWindows::translateEscapeReturnStatusToZeResult(escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
|
||||
}
|
||||
return ZE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
ze_result_t DebugSessionWindows::writeGpuMemory(uint64_t memoryHandle, const char *input, size_t size, uint64_t gpuVa) {
|
||||
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
|
||||
|
||||
auto gmmHelper = connectedDevice->getNEODevice()->getGmmHelper();
|
||||
gpuVa = gmmHelper->decanonize(gpuVa);
|
||||
|
||||
KM_ESCAPE_INFO escapeInfo = {0};
|
||||
escapeInfo.KmEuDbgL0EscapeInfo.EscapeActionType = DBGUMD_ACTION_WRITE_GFX_MEMORY;
|
||||
escapeInfo.KmEuDbgL0EscapeInfo.ReadGfxMemoryParams.hContextHandle = memoryHandle;
|
||||
escapeInfo.KmEuDbgL0EscapeInfo.ReadGfxMemoryParams.GpuVirtualAddr = gpuVa;
|
||||
escapeInfo.KmEuDbgL0EscapeInfo.ReadGfxMemoryParams.MemoryBufferSize = static_cast<uint32_t>(size);
|
||||
escapeInfo.KmEuDbgL0EscapeInfo.ReadGfxMemoryParams.MemoryBufferPtr = reinterpret_cast<uint64_t>(input);
|
||||
|
||||
auto status = runEscape(escapeInfo);
|
||||
if (STATUS_SUCCESS != status || DBGUMD_RETURN_ESCAPE_SUCCESS != escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus) {
|
||||
PRINT_DEBUGGER_ERROR_LOG("DBGUMD_ACTION_READ_GFX_MEMORY: Failed - ProcessId: %d Status: %d EscapeReturnStatus: %d\n", processId, status, escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
|
||||
return DebugSessionWindows::translateEscapeReturnStatusToZeResult(escapeInfo.KmEuDbgL0EscapeInfo.EscapeReturnStatus);
|
||||
}
|
||||
return ZE_RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
void DebugSessionWindows::enqueueApiEvent(zet_debug_event_t &debugEvent) {
|
||||
|
||||
@@ -41,6 +41,8 @@ struct DebugSessionWindows : DebugSessionImp {
|
||||
|
||||
ze_result_t readGpuMemory(uint64_t memoryHandle, char *output, size_t size, uint64_t gpuVa) override;
|
||||
ze_result_t writeGpuMemory(uint64_t memoryHandle, const char *input, size_t size, uint64_t gpuVa) override;
|
||||
bool isVAElf(const zet_debug_memory_space_desc_t *desc, size_t size);
|
||||
ze_result_t readElfSpace(const zet_debug_memory_space_desc_t *desc, size_t size, void *buffer);
|
||||
|
||||
ze_result_t readSbaBuffer(EuThread::ThreadId, SbaTrackedAddresses &sbaBuffer) override;
|
||||
|
||||
@@ -67,8 +69,9 @@ struct DebugSessionWindows : DebugSessionImp {
|
||||
|
||||
bool moduleDebugAreaCaptured = false;
|
||||
uint32_t processId = 0;
|
||||
uint64_t debugHandle = 0;
|
||||
NEO::Wddm *wddm = nullptr;
|
||||
constexpr static uint64_t invalidHandle = std::numeric_limits<uint64_t>::max();
|
||||
uint64_t debugHandle = invalidHandle;
|
||||
|
||||
struct ElfRange {
|
||||
uint64_t startVA;
|
||||
|
||||
@@ -21,13 +21,18 @@ struct MockDebugSessionWindows : DebugSessionWindows {
|
||||
using DebugSessionWindows::asyncThread;
|
||||
using DebugSessionWindows::closeAsyncThread;
|
||||
using DebugSessionWindows::debugHandle;
|
||||
using DebugSessionWindows::ElfRange;
|
||||
using DebugSessionWindows::initialize;
|
||||
using DebugSessionWindows::invalidHandle;
|
||||
using DebugSessionWindows::moduleDebugAreaCaptured;
|
||||
using DebugSessionWindows::processId;
|
||||
using DebugSessionWindows::readAllocationDebugData;
|
||||
using DebugSessionWindows::readAndHandleEvent;
|
||||
using DebugSessionWindows::readGpuMemory;
|
||||
using DebugSessionWindows::startAsyncThread;
|
||||
using DebugSessionWindows::wddm;
|
||||
using DebugSessionWindows::writeGpuMemory;
|
||||
using L0::DebugSessionImp::isValidGpuAddress;
|
||||
|
||||
MockDebugSessionWindows(const zet_debug_config_t &config, L0::Device *device) : DebugSessionWindows(config, device) {}
|
||||
|
||||
@@ -45,6 +50,14 @@ struct MockDebugSessionWindows : DebugSessionWindows {
|
||||
return DebugSessionWindows::readAndHandleEvent(timeoutMs);
|
||||
}
|
||||
|
||||
void ensureThreadStopped(ze_device_thread_t thread, uint64_t context) {
|
||||
auto threadId = convertToThreadId(thread);
|
||||
if (allThreads.find(threadId) == allThreads.end()) {
|
||||
allThreads[threadId] = std::make_unique<EuThread>(threadId);
|
||||
}
|
||||
allThreads[threadId]->stopThread(context);
|
||||
}
|
||||
|
||||
ze_result_t resultInitialize = ZE_RESULT_FORCE_UINT32;
|
||||
ze_result_t resultReadAndHandleEvent = ZE_RESULT_FORCE_UINT32;
|
||||
static constexpr uint64_t mockDebugHandle = 1;
|
||||
@@ -61,7 +74,7 @@ struct DebugApiWindowsFixture : public DeviceFixture {
|
||||
void TearDown() {
|
||||
DeviceFixture::TearDown();
|
||||
}
|
||||
|
||||
static constexpr uint8_t bufferSize = 16;
|
||||
WddmEuDebugInterfaceMock *mockWddm = nullptr;
|
||||
};
|
||||
|
||||
@@ -428,6 +441,7 @@ using DebugApiWindowsAsyncThreadTest = Test<DebugApiWindowsFixture>;
|
||||
TEST_F(DebugApiWindowsAsyncThreadTest, GivenDebugSessionWhenStartingAndClosingAsyncThreadThenThreadIsStartedAndFinishes) {
|
||||
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
|
||||
ASSERT_NE(nullptr, session);
|
||||
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
|
||||
session->wddm = mockWddm;
|
||||
session->startAsyncThread();
|
||||
|
||||
@@ -443,9 +457,8 @@ TEST_F(DebugApiWindowsAsyncThreadTest, GivenDebugSessionWhenStartingAndClosingAs
|
||||
TEST_F(DebugApiWindowsAsyncThreadTest, GivenDebugSessionWithAsyncThreadWhenClosingConnectionThenAsyncThreadIsTerminated) {
|
||||
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
|
||||
ASSERT_NE(nullptr, session);
|
||||
session->wddm = mockWddm;
|
||||
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
|
||||
|
||||
session->wddm = mockWddm;
|
||||
session->startAsyncThread();
|
||||
|
||||
EXPECT_TRUE(session->asyncThread.threadActive);
|
||||
@@ -457,5 +470,383 @@ TEST_F(DebugApiWindowsAsyncThreadTest, GivenDebugSessionWithAsyncThreadWhenClosi
|
||||
EXPECT_TRUE(session->asyncThread.threadFinished);
|
||||
}
|
||||
|
||||
TEST_F(DebugApiWindowsTest, WhenCallingReadGpuMemoryThenMemoryIsRead) {
|
||||
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
|
||||
ASSERT_NE(nullptr, session);
|
||||
session->wddm = mockWddm;
|
||||
|
||||
char output[bufferSize] = {};
|
||||
auto result = session->readGpuMemory(7, output, bufferSize, 0x1234);
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
|
||||
EXPECT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]);
|
||||
|
||||
for (int i = 0; i < bufferSize; i++) {
|
||||
EXPECT_EQ(static_cast<char>(0xaa), output[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(DebugApiWindowsTest, WhenCallingWriteGpuMemoryThenMemoryIsWritten) {
|
||||
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
|
||||
ASSERT_NE(nullptr, session);
|
||||
session->wddm = mockWddm;
|
||||
|
||||
char input[bufferSize] = {'h', 'e', 'l', 'l', 'o'};
|
||||
auto result = session->writeGpuMemory(7, input, bufferSize, 0x1234);
|
||||
ASSERT_EQ(ZE_RESULT_SUCCESS, result);
|
||||
ASSERT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_WRITE_GFX_MEMORY]);
|
||||
ASSERT_EQ(0, memcmp(input, mockWddm->testBuffer, bufferSize));
|
||||
}
|
||||
|
||||
TEST_F(DebugApiWindowsTest, GivenInvalidDebugHandleWhenWritingMemoryThenErrorIsReturned) {
|
||||
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
|
||||
ASSERT_NE(nullptr, session);
|
||||
session->wddm = mockWddm;
|
||||
session->debugHandle = MockDebugSessionWindows::invalidHandle;
|
||||
|
||||
ze_device_thread_t thread{0, 0, 0, 0};
|
||||
|
||||
zet_debug_memory_space_desc_t desc = {};
|
||||
|
||||
char output[bufferSize] = {};
|
||||
auto retVal = session->writeMemory(thread, &desc, bufferSize, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_UNINITIALIZED, retVal);
|
||||
}
|
||||
|
||||
TEST_F(DebugApiWindowsTest, GivenInvalidDebugHandleWhenReadingMemoryThenErrorIsReturned) {
|
||||
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
|
||||
ASSERT_NE(nullptr, session);
|
||||
session->wddm = mockWddm;
|
||||
session->debugHandle = MockDebugSessionWindows::invalidHandle;
|
||||
|
||||
ze_device_thread_t thread{0, 0, 0, 0};
|
||||
|
||||
zet_debug_memory_space_desc_t desc = {};
|
||||
|
||||
char output[bufferSize] = {};
|
||||
auto retVal = session->readMemory(thread, &desc, bufferSize, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_UNINITIALIZED, retVal);
|
||||
}
|
||||
TEST_F(DebugApiWindowsTest, GivenInvalidAddressWhenCallingReadMemoryThenErrorIsReturned) {
|
||||
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
|
||||
ASSERT_NE(nullptr, session);
|
||||
session->wddm = mockWddm;
|
||||
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
|
||||
|
||||
ze_device_thread_t thread{0, 0, 0, 0};
|
||||
|
||||
zet_debug_memory_space_desc_t desc;
|
||||
desc.address = 0xf0ffffff00000000;
|
||||
desc.type = ZET_DEBUG_MEMORY_SPACE_TYPE_DEFAULT;
|
||||
|
||||
EXPECT_FALSE(session->isValidGpuAddress(desc.address));
|
||||
|
||||
char output[bufferSize] = {};
|
||||
auto retVal = session->readMemory(thread, &desc, bufferSize, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, retVal);
|
||||
}
|
||||
|
||||
TEST_F(DebugApiWindowsTest, GivenInvalidAddressWhenCallingWriteMemoryThenErrorIsReturned) {
|
||||
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
|
||||
ASSERT_NE(nullptr, session);
|
||||
session->wddm = mockWddm;
|
||||
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
|
||||
|
||||
ze_device_thread_t thread{0, 0, 0, 0};
|
||||
|
||||
zet_debug_memory_space_desc_t desc;
|
||||
desc.address = 0xf0ffffff00000000;
|
||||
desc.type = ZET_DEBUG_MEMORY_SPACE_TYPE_DEFAULT;
|
||||
|
||||
EXPECT_FALSE(session->isValidGpuAddress(desc.address));
|
||||
|
||||
char output[bufferSize] = {};
|
||||
auto retVal = session->writeMemory(thread, &desc, bufferSize, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, retVal);
|
||||
}
|
||||
|
||||
TEST_F(DebugApiWindowsTest, WhenCallingWriteMemoryForAllThreadThenMemoryIsWritten) {
|
||||
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
|
||||
ASSERT_NE(nullptr, session);
|
||||
session->wddm = mockWddm;
|
||||
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
|
||||
|
||||
ze_device_thread_t thread;
|
||||
thread.slice = UINT32_MAX;
|
||||
thread.subslice = UINT32_MAX;
|
||||
thread.eu = UINT32_MAX;
|
||||
thread.thread = UINT32_MAX;
|
||||
zet_debug_memory_space_desc_t desc;
|
||||
desc.address = 0x1000;
|
||||
desc.type = ZET_DEBUG_MEMORY_SPACE_TYPE_DEFAULT;
|
||||
|
||||
char input[bufferSize] = {'a', 'b', 'c'};
|
||||
// No context yet created.
|
||||
auto retVal = session->writeMemory(thread, &desc, bufferSize, input);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_UNINITIALIZED, retVal);
|
||||
|
||||
session->allContexts.insert(0x12345);
|
||||
|
||||
retVal = session->writeMemory(thread, &desc, bufferSize, input);
|
||||
ASSERT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_WRITE_GFX_MEMORY]);
|
||||
ASSERT_EQ(0, memcmp(input, mockWddm->testBuffer, bufferSize));
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, retVal);
|
||||
}
|
||||
|
||||
TEST_F(DebugApiWindowsTest, WhenCallingWriteMemoryForSingleThreadThenMemoryIsWritten) {
|
||||
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
|
||||
ASSERT_NE(nullptr, session);
|
||||
session->wddm = mockWddm;
|
||||
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
|
||||
session->allContexts.insert(0x12345);
|
||||
|
||||
ze_device_thread_t thread;
|
||||
thread.slice = 1;
|
||||
thread.subslice = 1;
|
||||
thread.eu = 1;
|
||||
thread.thread = 1;
|
||||
zet_debug_memory_space_desc_t desc;
|
||||
desc.address = 0x1000;
|
||||
desc.type = ZET_DEBUG_MEMORY_SPACE_TYPE_DEFAULT;
|
||||
|
||||
char input[bufferSize] = {'a', 'b', 'c'};
|
||||
session->ensureThreadStopped(thread, EuThread::invalidHandle);
|
||||
auto retVal = session->writeMemory(thread, &desc, bufferSize, input);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, retVal);
|
||||
ASSERT_EQ(0, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_WRITE_GFX_MEMORY]);
|
||||
|
||||
session->ensureThreadStopped(thread, 0x12345);
|
||||
retVal = session->writeMemory(thread, &desc, bufferSize, input);
|
||||
ASSERT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_WRITE_GFX_MEMORY]);
|
||||
ASSERT_EQ(0, memcmp(input, mockWddm->testBuffer, bufferSize));
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, retVal);
|
||||
}
|
||||
|
||||
TEST_F(DebugApiWindowsTest, WhenCallingReadMemoryForAllThreadThenMemoryIsWritten) {
|
||||
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
|
||||
ASSERT_NE(nullptr, session);
|
||||
session->wddm = mockWddm;
|
||||
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
|
||||
|
||||
ze_device_thread_t thread;
|
||||
thread.slice = UINT32_MAX;
|
||||
thread.subslice = UINT32_MAX;
|
||||
thread.eu = UINT32_MAX;
|
||||
thread.thread = UINT32_MAX;
|
||||
zet_debug_memory_space_desc_t desc;
|
||||
desc.address = 0x1000;
|
||||
desc.type = ZET_DEBUG_MEMORY_SPACE_TYPE_DEFAULT;
|
||||
|
||||
char output[bufferSize] = {0};
|
||||
// No context yet created.
|
||||
auto retVal = session->readMemory(thread, &desc, bufferSize, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_UNINITIALIZED, retVal);
|
||||
|
||||
session->allContexts.insert(0x12345);
|
||||
|
||||
retVal = session->readMemory(thread, &desc, bufferSize, output);
|
||||
ASSERT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]);
|
||||
for (int i = 0; i < bufferSize; i++) {
|
||||
EXPECT_EQ(static_cast<char>(0xaa), output[i]);
|
||||
}
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, retVal);
|
||||
}
|
||||
|
||||
TEST_F(DebugApiWindowsTest, WhenCallingReadMemoryForSingleThreadThenMemoryIsRead) {
|
||||
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
|
||||
ASSERT_NE(nullptr, session);
|
||||
session->wddm = mockWddm;
|
||||
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
|
||||
session->allContexts.insert(0x12345);
|
||||
|
||||
ze_device_thread_t thread;
|
||||
thread.slice = 1;
|
||||
thread.subslice = 1;
|
||||
thread.eu = 1;
|
||||
thread.thread = 1;
|
||||
zet_debug_memory_space_desc_t desc;
|
||||
desc.address = 0x1000;
|
||||
desc.type = ZET_DEBUG_MEMORY_SPACE_TYPE_DEFAULT;
|
||||
|
||||
char output[bufferSize] = {0};
|
||||
|
||||
session->ensureThreadStopped(thread, EuThread::invalidHandle);
|
||||
auto retVal = session->readMemory(thread, &desc, bufferSize, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, retVal);
|
||||
ASSERT_EQ(0, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]);
|
||||
|
||||
session->ensureThreadStopped(thread, 0x12345);
|
||||
|
||||
retVal = session->readMemory(thread, &desc, bufferSize, output);
|
||||
ASSERT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]);
|
||||
for (int i = 0; i < bufferSize; i++) {
|
||||
EXPECT_EQ(static_cast<char>(0xaa), output[i]);
|
||||
}
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, retVal);
|
||||
}
|
||||
|
||||
TEST_F(DebugApiWindowsTest, WhenCallingReadMemoryForElfThenUnsupportedFeatureIsReturned) {
|
||||
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
|
||||
ASSERT_NE(nullptr, session);
|
||||
session->wddm = mockWddm;
|
||||
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
|
||||
session->allContexts.insert(0x12345);
|
||||
|
||||
uint64_t elfSize = 0xFF;
|
||||
char *elfData = new char[elfSize];
|
||||
memset(elfData, 0xa, elfSize);
|
||||
|
||||
uint64_t elfVaStart = reinterpret_cast<uint64_t>(elfData);
|
||||
uint64_t elfVaEnd = reinterpret_cast<uint64_t>(elfData) + elfSize;
|
||||
|
||||
MockDebugSessionWindows::ElfRange elf = {elfVaStart, elfVaEnd};
|
||||
session->allElfs.push_back(elf);
|
||||
char output[bufferSize] = {0};
|
||||
|
||||
ze_device_thread_t thread;
|
||||
thread.slice = UINT32_MAX;
|
||||
thread.subslice = UINT32_MAX;
|
||||
thread.eu = UINT32_MAX;
|
||||
thread.thread = UINT32_MAX;
|
||||
zet_debug_memory_space_desc_t desc;
|
||||
desc.address = elfVaStart;
|
||||
desc.type = ZET_DEBUG_MEMORY_SPACE_TYPE_DEFAULT;
|
||||
auto retVal = session->readMemory(thread, &desc, bufferSize, output);
|
||||
ASSERT_EQ(0, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, retVal);
|
||||
|
||||
desc.address = elfVaEnd - 1;
|
||||
retVal = session->readMemory(thread, &desc, bufferSize, output);
|
||||
ASSERT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]);
|
||||
EXPECT_EQ(ZE_RESULT_SUCCESS, retVal);
|
||||
|
||||
delete[] elfData;
|
||||
}
|
||||
|
||||
TEST_F(DebugApiWindowsTest, WhenCallingWriteMemoryForExpectedFailureCasesThenErrorIsReturned) {
|
||||
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
|
||||
ASSERT_NE(nullptr, session);
|
||||
session->wddm = mockWddm;
|
||||
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
|
||||
session->allContexts.insert(0x12345);
|
||||
|
||||
ze_device_thread_t thread = {};
|
||||
zet_debug_memory_space_desc_t desc;
|
||||
desc.address = 0x2000;
|
||||
|
||||
char output[bufferSize] = {};
|
||||
size_t size = bufferSize;
|
||||
|
||||
desc.type = ZET_DEBUG_MEMORY_SPACE_TYPE_SLM;
|
||||
auto retVal = session->writeMemory(thread, &desc, size, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, retVal);
|
||||
|
||||
desc.type = ZET_DEBUG_MEMORY_SPACE_TYPE_DEFAULT;
|
||||
|
||||
thread.slice = UINT32_MAX;
|
||||
thread.subslice = 0;
|
||||
thread.eu = 0;
|
||||
thread.thread = 0;
|
||||
|
||||
retVal = session->writeMemory(thread, &desc, size, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, retVal);
|
||||
|
||||
thread.slice = UINT32_MAX;
|
||||
thread.subslice = UINT32_MAX;
|
||||
thread.eu = 0;
|
||||
thread.thread = 0;
|
||||
|
||||
retVal = session->writeMemory(thread, &desc, size, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, retVal);
|
||||
|
||||
thread.slice = UINT32_MAX;
|
||||
thread.subslice = UINT32_MAX;
|
||||
thread.eu = UINT32_MAX;
|
||||
thread.thread = 0;
|
||||
|
||||
retVal = session->writeMemory(thread, &desc, size, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, retVal);
|
||||
|
||||
thread.slice = UINT32_MAX;
|
||||
thread.subslice = UINT32_MAX;
|
||||
thread.eu = UINT32_MAX;
|
||||
thread.thread = UINT32_MAX;
|
||||
|
||||
mockWddm->escapeReturnStatus = DBGUMD_RETURN_INVALID_ARGS;
|
||||
retVal = session->writeMemory(thread, &desc, size, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, retVal);
|
||||
mockWddm->escapeReturnStatus = DBGUMD_RETURN_ESCAPE_SUCCESS;
|
||||
|
||||
thread.slice = 0;
|
||||
thread.subslice = 0;
|
||||
thread.eu = 0;
|
||||
thread.thread = 0;
|
||||
|
||||
retVal = session->writeMemory(thread, &desc, size, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, retVal);
|
||||
}
|
||||
|
||||
TEST_F(DebugApiWindowsTest, WhenCallingReadMemoryForExpectedFailureCasesThenErrorIsReturned) {
|
||||
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
|
||||
ASSERT_NE(nullptr, session);
|
||||
session->wddm = mockWddm;
|
||||
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
|
||||
session->allContexts.insert(0x12345);
|
||||
|
||||
ze_device_thread_t thread = {};
|
||||
zet_debug_memory_space_desc_t desc;
|
||||
desc.address = 0x2000;
|
||||
|
||||
char output[bufferSize] = {};
|
||||
size_t size = bufferSize;
|
||||
|
||||
desc.type = ZET_DEBUG_MEMORY_SPACE_TYPE_SLM;
|
||||
auto retVal = session->readMemory(thread, &desc, size, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, retVal);
|
||||
|
||||
desc.type = ZET_DEBUG_MEMORY_SPACE_TYPE_DEFAULT;
|
||||
|
||||
thread.slice = UINT32_MAX;
|
||||
thread.subslice = 0;
|
||||
thread.eu = 0;
|
||||
thread.thread = 0;
|
||||
|
||||
retVal = session->readMemory(thread, &desc, size, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, retVal);
|
||||
|
||||
thread.slice = UINT32_MAX;
|
||||
thread.subslice = UINT32_MAX;
|
||||
thread.eu = 0;
|
||||
thread.thread = 0;
|
||||
|
||||
retVal = session->readMemory(thread, &desc, size, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, retVal);
|
||||
|
||||
thread.slice = UINT32_MAX;
|
||||
thread.subslice = UINT32_MAX;
|
||||
thread.eu = UINT32_MAX;
|
||||
thread.thread = 0;
|
||||
|
||||
retVal = session->readMemory(thread, &desc, size, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, retVal);
|
||||
|
||||
thread.slice = UINT32_MAX;
|
||||
thread.subslice = UINT32_MAX;
|
||||
thread.eu = UINT32_MAX;
|
||||
thread.thread = UINT32_MAX;
|
||||
|
||||
mockWddm->escapeReturnStatus = DBGUMD_RETURN_INVALID_ARGS;
|
||||
retVal = session->readMemory(thread, &desc, size, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_INVALID_ARGUMENT, retVal);
|
||||
mockWddm->escapeReturnStatus = DBGUMD_RETURN_ESCAPE_SUCCESS;
|
||||
|
||||
thread.slice = 0;
|
||||
thread.subslice = 0;
|
||||
thread.eu = 0;
|
||||
thread.thread = 0;
|
||||
|
||||
retVal = session->readMemory(thread, &desc, size, output);
|
||||
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, retVal);
|
||||
}
|
||||
|
||||
} // namespace ult
|
||||
} // namespace L0
|
||||
|
||||
Reference in New Issue
Block a user