L0 Win Debug - read StateSave and moduleDebug header

Related-to: NEO-7162
Signed-off-by: Yates, Brandon <brandon.yates@intel.com>
This commit is contained in:
Yates, Brandon
2022-06-29 14:40:45 +00:00
committed by Compute-Runtime-Automation
parent b225c63b9a
commit 7ccde3fb20
7 changed files with 236 additions and 14 deletions

View File

@@ -717,6 +717,18 @@ void DebugSessionImp::generateEventsForStoppedThreads(const std::vector<EuThread
}
}
void DebugSessionImp::validateAndSetStateSaveAreaHeader(const std::vector<char> &data) {
auto pStateSaveArea = reinterpret_cast<const SIP::StateSaveAreaHeader *>(data.data());
if (0 == strcmp(pStateSaveArea->versionHeader.magic, "tssarea")) {
size_t size = pStateSaveArea->versionHeader.size * 8u;
DEBUG_BREAK_IF(size != sizeof(SIP::StateSaveAreaHeader));
stateSaveAreaHeader.assign(data.begin(), data.begin() + size);
PRINT_DEBUGGER_INFO_LOG("Context State Save Area : version == %d.%d.%d\n", (int)pStateSaveArea->versionHeader.version.major, (int)pStateSaveArea->versionHeader.version.minor, (int)pStateSaveArea->versionHeader.version.patch);
} else {
PRINT_DEBUGGER_ERROR_LOG("Setting Context State Save Area: failed to match magic numbers\n", "");
}
}
const SIP::StateSaveAreaHeader *DebugSessionImp::getStateSaveAreaHeader() {
if (stateSaveAreaHeader.empty()) {
readStateSaveAreaHeader();

View File

@@ -69,6 +69,7 @@ struct DebugSessionImp : DebugSession {
MOCKABLE_VIRTUAL void generateEventsForPendingInterrupts();
const SIP::StateSaveAreaHeader *getStateSaveAreaHeader();
void validateAndSetStateSaveAreaHeader(const std::vector<char> &data);
virtual void readStateSaveAreaHeader(){};
virtual uint64_t getContextStateSaveAreaGpuVa(uint64_t memoryHandle) {

View File

@@ -647,14 +647,7 @@ void DebugSessionLinux::readStateSaveAreaHeader() {
if (retVal != 0) {
PRINT_DEBUGGER_ERROR_LOG("Reading Context State Save Area failed, error = %d\n", retVal);
} else {
auto pStateSaveArea = reinterpret_cast<const SIP::StateSaveAreaHeader *>(data.data());
if (0 == strcmp(pStateSaveArea->versionHeader.magic, "tssarea")) {
size_t size = pStateSaveArea->versionHeader.size * 8u;
DEBUG_BREAK_IF(size != sizeof(SIP::StateSaveAreaHeader));
stateSaveAreaHeader.assign(data.begin(), data.begin() + size);
PRINT_DEBUGGER_INFO_LOG("Context State Save Area : version == %d.%d.%d\n", (int)pStateSaveArea->versionHeader.version.major, (int)pStateSaveArea->versionHeader.version.minor, (int)pStateSaveArea->versionHeader.version.patch);
}
validateAndSetStateSaveAreaHeader(data);
}
}
}

View File

@@ -9,6 +9,8 @@
#include "shared/source/helpers/register_offsets.h"
#include "common/StateSaveAreaHeader.h"
namespace L0 {
DebugSession *createDebugSessionHelper(const zet_debug_config_t &config, Device *device, int debugFd);
@@ -60,11 +62,13 @@ ze_result_t DebugSessionWindows::initialize() {
PRINT_DEBUGGER_INFO_LOG("DBGUMD_ACTION_ATTACH_DEBUGGER: SUCCESS - ProcessId: %d DebugHandle: 0x%llx\n", processId, debugHandle);
auto result = ZE_RESULT_SUCCESS;
do {
result = readAndHandleEvent(100);
} while (result == ZE_RESULT_SUCCESS && !moduleDebugAreaCaptured);
if (moduleDebugAreaCaptured) {
readModuleDebugArea();
return ZE_RESULT_SUCCESS;
}
@@ -203,7 +207,13 @@ ze_result_t DebugSessionWindows::handleAllocationDataEvent(uint32_t seqNo, DBGUM
}
if (allocationDebugData->DataType == MODULE_HEAP_DEBUG_AREA) {
DEBUG_BREAK_IF(moduleDebugAreaCaptured && (registrationData.gpuVirtualAddress != this->debugAreaVA));
moduleDebugAreaCaptured = true;
this->debugAreaVA = registrationData.gpuVirtualAddress;
} else if (allocationDebugData->DataType == SIP_CONTEXT_SAVE_AREA) {
DEBUG_BREAK_IF(stateSaveAreaCaptured && (registrationData.gpuVirtualAddress != this->stateSaveAreaVA.load()));
stateSaveAreaVA.store(registrationData.gpuVirtualAddress);
stateSaveAreaCaptured = true;
}
PRINT_DEBUGGER_INFO_LOG("DBGUMD_ACTION_READ_ALLOCATION_DATA - Success - gpuVA=0x%llX Size=0x%X\n", registrationData.gpuVirtualAddress, registrationData.size);
}
@@ -454,10 +464,6 @@ bool DebugSessionWindows::readSystemRoutineIdent(EuThread *thread, uint64_t vmHa
return false;
}
bool DebugSessionWindows::readModuleDebugArea() {
return false;
}
ze_result_t DebugSessionWindows::readSbaBuffer(EuThread::ThreadId threadId, NEO::SbaTrackedAddresses &sbaBuffer) {
uint64_t gpuVa = 0;
getSbaBufferGpuVa(gpuVa);
@@ -493,4 +499,58 @@ void DebugSessionWindows::getSbaBufferGpuVa(uint64_t &gpuVa) {
return;
}
bool DebugSessionWindows::readModuleDebugArea() {
uint64_t memoryHandle = 0;
uint64_t gpuVa = this->debugAreaVA;
if (!moduleDebugAreaCaptured || allContexts.empty()) {
return false;
}
memoryHandle = *allContexts.begin();
memset(this->debugArea.magic, 0, sizeof(this->debugArea.magic));
auto retVal = readGpuMemory(memoryHandle, reinterpret_cast<char *>(&this->debugArea), sizeof(this->debugArea), gpuVa);
if (retVal != ZE_RESULT_SUCCESS) {
PRINT_DEBUGGER_ERROR_LOG("Reading Module Debug Area failed, error = %d\n", retVal);
return false;
}
if (strncmp(this->debugArea.magic, "dbgarea", sizeof(NEO::DebugAreaHeader::magic)) != 0) {
PRINT_DEBUGGER_ERROR_LOG("Module Debug Area failed to match magic numbers\n");
return false;
}
PRINT_DEBUGGER_INFO_LOG("Reading Module Debug Area Passed");
return true;
}
void DebugSessionWindows::readStateSaveAreaHeader() {
uint64_t memoryHandle = 0;
uint64_t gpuVa = 0;
if (!stateSaveAreaCaptured) {
return;
}
gpuVa = this->stateSaveAreaVA.load();
{
std::unique_lock<std::mutex> lock(asyncThreadMutex);
if (allContexts.empty()) {
return;
}
memoryHandle = *allContexts.begin();
}
auto headerSize = sizeof(SIP::StateSaveAreaHeader);
std::vector<char> data(headerSize);
auto retVal = readGpuMemory(memoryHandle, data.data(), headerSize, gpuVa);
if (retVal != ZE_RESULT_SUCCESS) {
PRINT_DEBUGGER_ERROR_LOG("Reading Context State Save Area failed, error = %d\n", retVal);
return;
}
validateAndSetStateSaveAreaHeader(data);
}
} // namespace L0

View File

@@ -16,6 +16,7 @@
#include "KmEscape.h"
#include <atomic>
#include <unordered_set>
namespace L0 {
@@ -45,6 +46,7 @@ struct DebugSessionWindows : DebugSessionImp {
ze_result_t readElfSpace(const zet_debug_memory_space_desc_t *desc, size_t size, void *buffer);
ze_result_t readSbaBuffer(EuThread::ThreadId, NEO::SbaTrackedAddresses &sbaBuffer) override;
void readStateSaveAreaHeader() override;
MOCKABLE_VIRTUAL ze_result_t readAndHandleEvent(uint64_t timeoutMs);
ze_result_t handleModuleCreateEvent(DBGUMD_READ_EVENT_MODULE_CREATE_EVENT_PARAMS &moduleCreateParams);
@@ -65,7 +67,6 @@ struct DebugSessionWindows : DebugSessionImp {
ThreadHelper asyncThread;
std::mutex asyncThreadMutex;
MOCKABLE_VIRTUAL void getSbaBufferGpuVa(uint64_t &gpuVa);
MOCKABLE_VIRTUAL NTSTATUS runEscape(KM_ESCAPE_INFO &escapeInfo);
bool moduleDebugAreaCaptured = false;
@@ -79,6 +80,11 @@ struct DebugSessionWindows : DebugSessionImp {
uint64_t endVA;
};
uint64_t debugAreaVA;
NEO::DebugAreaHeader debugArea;
std::atomic<uint64_t> stateSaveAreaVA{0};
bool stateSaveAreaCaptured = false;
std::unordered_set<uint64_t> allContexts;
std::vector<ElfRange> allElfs;
};

View File

@@ -5,13 +5,17 @@
*
*/
#include "shared/source/built_ins/sip.h"
#include "shared/source/os_interface/windows/wddm_allocation.h"
#include "shared/test/common/mocks/mock_sip.h"
#include "shared/test/common/mocks/windows/mock_wddm_eudebug.h"
#include "shared/test/common/test_macros/hw_test.h"
#include "level_zero/core/test/unit_tests/fixtures/device_fixture.h"
#include "level_zero/tools/source/debug/windows/debug_session.h"
#include "common/StateSaveAreaHeader.h"
namespace L0 {
namespace ult {
@@ -20,6 +24,8 @@ struct MockDebugSessionWindows : DebugSessionWindows {
using DebugSessionWindows::allElfs;
using DebugSessionWindows::asyncThread;
using DebugSessionWindows::closeAsyncThread;
using DebugSessionWindows::debugArea;
using DebugSessionWindows::debugAreaVA;
using DebugSessionWindows::debugHandle;
using DebugSessionWindows::ElfRange;
using DebugSessionWindows::getSbaBufferGpuVa;
@@ -30,11 +36,16 @@ struct MockDebugSessionWindows : DebugSessionWindows {
using DebugSessionWindows::readAllocationDebugData;
using DebugSessionWindows::readAndHandleEvent;
using DebugSessionWindows::readGpuMemory;
using DebugSessionWindows::readModuleDebugArea;
using DebugSessionWindows::readSbaBuffer;
using DebugSessionWindows::readStateSaveAreaHeader;
using DebugSessionWindows::runEscape;
using DebugSessionWindows::startAsyncThread;
using DebugSessionWindows::stateSaveAreaCaptured;
using DebugSessionWindows::stateSaveAreaVA;
using DebugSessionWindows::wddm;
using DebugSessionWindows::writeGpuMemory;
using L0::DebugSessionImp::getStateSaveAreaHeader;
using L0::DebugSessionImp::isValidGpuAddress;
MockDebugSessionWindows(const zet_debug_config_t &config, L0::Device *device) : DebugSessionWindows(config, device) {}
@@ -336,6 +347,7 @@ TEST_F(DebugApiWindowsTest, givenDebugSessionInitializeCalledAndEventQueueIsNotA
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_TRUE(session->moduleDebugAreaCaptured);
EXPECT_EQ(session->debugAreaVA, 0x12345678U);
EXPECT_EQ(1u, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_ATTACH_DEBUGGER]);
EXPECT_EQ(3u, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_EVENT]);
EXPECT_EQ(1u, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_ALLOCATION_DATA]);
@@ -470,6 +482,27 @@ TEST_F(DebugApiWindowsTest, givenDebugDataEventTypeWhenReadAndHandleEventCalledT
EXPECT_EQ(elf.endVA, 0xa008u);
}
TEST_F(DebugApiWindowsTest, givenAllocationEventTypeForStateSaveWhenReadAndHandleEventCalledThenStateSaveIsCaptured) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionWindows>(config, device);
session->wddm = mockWddm;
mockWddm->numEvents = 1;
mockWddm->eventQueue[0].readEventType = DBGUMD_READ_EVENT_ALLOCATION_DATA_INFO;
mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams.NumOfDebugData = 1;
GFX_ALLOCATION_DEBUG_DATA_INFO *allocDebugDataInfo = reinterpret_cast<GFX_ALLOCATION_DEBUG_DATA_INFO *>(&mockWddm->eventQueue[0].eventParamsBuffer.eventParamsBuffer.ReadAdditionalAllocDataParams.DebugDataBufferPtr);
allocDebugDataInfo->DataType = SIP_CONTEXT_SAVE_AREA;
WddmAllocation::RegistrationData registrationData = {0x12345678, 0x1000};
mockWddm->readAllocationDataOutParams.outData = &registrationData;
mockWddm->readAllocationDataOutParams.outDataSize = sizeof(registrationData);
EXPECT_EQ(ZE_RESULT_SUCCESS, session->readAndHandleEvent(100));
EXPECT_EQ(session->stateSaveAreaVA.load(), 0x12345678u);
EXPECT_TRUE(session->stateSaveAreaCaptured);
}
TEST_F(DebugApiWindowsTest, givenContextCreateEventTypeWhenReadAndHandleEventCalledThenAllContextsIsSetCorrectly) {
zet_debug_config_t config = {};
config.pid = 0x1234;
@@ -927,5 +960,117 @@ TEST_F(DebugApiWindowsTest, WhenCallingReadMemoryForExpectedFailureCasesThenErro
EXPECT_EQ(ZE_RESULT_ERROR_NOT_AVAILABLE, retVal);
}
TEST_F(DebugApiWindowsTest, GivenModuleDebugAreaVaWhenReadingModuleDebugAreaThenGpuMemoryIsRead) {
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);
session->moduleDebugAreaCaptured = true;
session->debugAreaVA = 0xABCDABCD;
DebugAreaHeader debugArea;
debugArea.reserved1 = 1;
debugArea.pgsize = uint8_t(4);
debugArea.version = 1;
mockWddm->srcReadBuffer = &debugArea;
auto retVal = session->readModuleDebugArea();
EXPECT_TRUE(retVal);
ASSERT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]);
EXPECT_EQ(1u, session->debugArea.reserved1);
EXPECT_EQ(1u, session->debugArea.version);
EXPECT_EQ(4u, session->debugArea.pgsize);
}
TEST_F(DebugApiWindowsTest, GivenModuleDebugAreaVaWhenReadingModuleDebugAreaReturnsIncorrectDataThenFailIsReturned) {
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);
session->moduleDebugAreaCaptured = true;
session->debugAreaVA = 0xABCDABCD;
DebugAreaHeader debugArea;
debugArea.magic[0] = 'x';
mockWddm->srcReadBuffer = &debugArea;
auto retVal = session->readModuleDebugArea();
EXPECT_FALSE(retVal);
}
TEST_F(DebugApiWindowsTest, GivenErrorInModuleDebugAreaDataWhenReadingModuleDebugAreaThenGpuMemoryIsNotReadAndFalseReturned) {
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
ASSERT_NE(nullptr, session);
session->wddm = mockWddm;
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
auto retVal = session->readModuleDebugArea();
EXPECT_FALSE(retVal);
ASSERT_EQ(0, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]);
session->moduleDebugAreaCaptured = true;
retVal = session->readModuleDebugArea();
EXPECT_FALSE(retVal);
ASSERT_EQ(0, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]);
session->allContexts.insert(0x12345);
mockWddm->escapeReturnStatus = DBGUMD_RETURN_INVALID_ARGS;
retVal = session->readModuleDebugArea();
EXPECT_FALSE(retVal);
ASSERT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]);
}
TEST_F(DebugApiWindowsTest, GivenStateSaveAreaVaWhenReadingStateSaveAreaThenGpuMemoryIsRead) {
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);
session->stateSaveAreaCaptured = true;
session->stateSaveAreaVA.store(0xABCDABCD);
auto stateSaveAreaHeader = MockSipData::createStateSaveAreaHeader(2);
mockWddm->srcReadBuffer = stateSaveAreaHeader.data();
session->readStateSaveAreaHeader();
ASSERT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]);
auto stateSaveAreaRead = session->getStateSaveAreaHeader();
ASSERT_NE(nullptr, stateSaveAreaRead);
EXPECT_EQ(0, memcmp(stateSaveAreaRead, stateSaveAreaHeader.data(), sizeof(SIP::StateSaveAreaHeader)));
}
TEST_F(DebugApiWindowsTest, GivenStateSaveAreaVaWhenReadingStateSaveAreaReturnsIncorrectDataThenStateSaveAreaIsNotUpdated) {
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);
session->stateSaveAreaCaptured = true;
session->stateSaveAreaVA.store(0xABCDABCD);
auto stateSaveAreaHeader = MockSipData::createStateSaveAreaHeader(2);
stateSaveAreaHeader[3] = 'x';
mockWddm->srcReadBuffer = stateSaveAreaHeader.data();
session->readStateSaveAreaHeader();
ASSERT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]);
auto stateSaveAreaRead = session->getStateSaveAreaHeader();
ASSERT_EQ(nullptr, stateSaveAreaRead);
}
TEST_F(DebugApiWindowsTest, GivenErrorCasesWhenReadingStateSaveAreThenMemoryIsNotRead) {
auto session = std::make_unique<MockDebugSessionWindows>(zet_debug_config_t{0x1234}, device);
ASSERT_NE(nullptr, session);
session->wddm = mockWddm;
session->debugHandle = MockDebugSessionWindows::mockDebugHandle;
session->readStateSaveAreaHeader();
ASSERT_EQ(0, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]);
session->stateSaveAreaCaptured = true;
session->readStateSaveAreaHeader();
ASSERT_EQ(0, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]);
session->allContexts.insert(0x12345);
mockWddm->escapeReturnStatus = DBGUMD_RETURN_INVALID_ARGS;
session->readStateSaveAreaHeader();
ASSERT_EQ(1, mockWddm->dbgUmdEscapeActionCalled[DBGUMD_ACTION_READ_GFX_MEMORY]);
}
} // namespace ult
} // namespace L0