mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-28 16:48:45 +08:00
feature: Implement thread control for debugger in XE
Related-To: NEO-9668 Signed-off-by: Jitendra Sharma <jitendra.sharma@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
4ea848f434
commit
ff604bda1b
@@ -350,4 +350,47 @@ ze_result_t DebugSessionLinux::writeGpuMemory(uint64_t vmHandle, const char *inp
|
||||
return (retVal == 0) ? ZE_RESULT_SUCCESS : ZE_RESULT_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
int DebugSessionLinux::threadControl(const std::vector<EuThread::ThreadId> &threads, uint32_t tile, ThreadControlCmd threadCmd, std::unique_ptr<uint8_t[]> &bitmaskOut, size_t &bitmaskSizeOut) {
|
||||
|
||||
auto hwInfo = connectedDevice->getHwInfo();
|
||||
auto classInstance = DrmHelper::getEngineInstance(connectedDevice, tile, hwInfo.capabilityTable.defaultEngineType);
|
||||
UNRECOVERABLE_IF(!classInstance);
|
||||
|
||||
auto &l0GfxCoreHelper = connectedDevice->getL0GfxCoreHelper();
|
||||
|
||||
bitmaskSizeOut = 0;
|
||||
std::unique_ptr<uint8_t[]> bitmask;
|
||||
size_t bitmaskSize = 0;
|
||||
|
||||
if (threadCmd == ThreadControlCmd::interrupt ||
|
||||
threadCmd == ThreadControlCmd::resume ||
|
||||
threadCmd == ThreadControlCmd::stopped) {
|
||||
l0GfxCoreHelper.getAttentionBitmaskForSingleThreads(threads, hwInfo, bitmask, bitmaskSize);
|
||||
}
|
||||
|
||||
uint64_t seqnoRet = 0;
|
||||
uint64_t bitmaskSizeRet = 0;
|
||||
auto euControlRetVal = euControlIoctl(threadCmd, classInstance, bitmask, bitmaskSize, seqnoRet, bitmaskSizeRet);
|
||||
if (euControlRetVal != 0) {
|
||||
PRINT_DEBUGGER_ERROR_LOG("euControl IOCTL failed: retCode: %d errno = %d threadCmd = %d\n", euControlRetVal, errno, threadCmd);
|
||||
} else {
|
||||
PRINT_DEBUGGER_INFO_LOG("euControl IOCTL: seqno = %llu threadCmd = %u\n", seqnoRet, threadCmd);
|
||||
}
|
||||
|
||||
if (threadCmd == ThreadControlCmd::interrupt ||
|
||||
threadCmd == ThreadControlCmd::interruptAll) {
|
||||
if (euControlRetVal == 0) {
|
||||
euControlInterruptSeqno[tile] = seqnoRet;
|
||||
} else {
|
||||
euControlInterruptSeqno[tile] = invalidHandle;
|
||||
}
|
||||
}
|
||||
|
||||
if (threadCmd == ThreadControlCmd::stopped) {
|
||||
bitmaskOut = std::move(bitmask);
|
||||
bitmaskSizeOut = bitmaskSizeRet;
|
||||
}
|
||||
return euControlRetVal;
|
||||
}
|
||||
|
||||
} // namespace L0
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "shared/source/os_interface/linux/drm_wrappers.h"
|
||||
#include "shared/source/os_interface/linux/sys_calls.h"
|
||||
|
||||
#include "level_zero/core/source/device/device.h"
|
||||
@@ -82,6 +83,7 @@ struct DebugSessionLinux : DebugSessionImp {
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
enum class ThreadControlCmd {
|
||||
interrupt,
|
||||
resume,
|
||||
@@ -89,11 +91,16 @@ struct DebugSessionLinux : DebugSessionImp {
|
||||
interruptAll
|
||||
};
|
||||
|
||||
virtual int threadControl(const std::vector<EuThread::ThreadId> &threads, uint32_t tile, ThreadControlCmd threadCmd, std::unique_ptr<uint8_t[]> &bitmask, size_t &bitmaskSize) = 0;
|
||||
virtual int euControlIoctl(ThreadControlCmd threadCmd,
|
||||
const NEO::EngineClassInstance *classInstance,
|
||||
std::unique_ptr<uint8_t[]> &bitmask,
|
||||
size_t bitmaskSize, uint64_t &seqnoOut, uint64_t &bitmaskSizeOut) = 0;
|
||||
MOCKABLE_VIRTUAL int threadControl(const std::vector<EuThread::ThreadId> &threads, uint32_t tile, ThreadControlCmd threadCmd, std::unique_ptr<uint8_t[]> &bitmask, size_t &bitmaskSize);
|
||||
void checkStoppedThreadsAndGenerateEvents(const std::vector<EuThread::ThreadId> &threads, uint64_t memoryHandle, uint32_t deviceIndex) override;
|
||||
MOCKABLE_VIRTUAL bool checkForceExceptionBit(uint64_t memoryHandle, EuThread::ThreadId threadId, uint32_t *cr0, const SIP::regset_desc *regDesc);
|
||||
ze_result_t resumeImp(const std::vector<EuThread::ThreadId> &threads, uint32_t deviceIndex) override;
|
||||
ze_result_t interruptImp(uint32_t deviceIndex) override;
|
||||
std::unique_ptr<IoctlHandler> ioctlHandler;
|
||||
uint64_t euControlInterruptSeqno[NEO::EngineLimits::maxHandleCount];
|
||||
};
|
||||
} // namespace L0
|
||||
@@ -1316,16 +1316,10 @@ uint64_t DebugSessionLinuxi915::extractVaFromUuidString(std::string &uuid) {
|
||||
return parts[0];
|
||||
}
|
||||
|
||||
int DebugSessionLinuxi915::threadControl(const std::vector<EuThread::ThreadId> &threads, uint32_t tile, ThreadControlCmd threadCmd, std::unique_ptr<uint8_t[]> &bitmaskOut, size_t &bitmaskSizeOut) {
|
||||
|
||||
auto hwInfo = connectedDevice->getHwInfo();
|
||||
auto classInstance = DrmHelper::getEngineInstance(connectedDevice, tile, hwInfo.capabilityTable.defaultEngineType);
|
||||
UNRECOVERABLE_IF(!classInstance);
|
||||
|
||||
auto &l0GfxCoreHelper = connectedDevice->getL0GfxCoreHelper();
|
||||
|
||||
bitmaskSizeOut = 0;
|
||||
|
||||
int DebugSessionLinuxi915::euControlIoctl(ThreadControlCmd threadCmd,
|
||||
const NEO::EngineClassInstance *classInstance,
|
||||
std::unique_ptr<uint8_t[]> &bitmask,
|
||||
size_t bitmaskSize, uint64_t &seqnoOut, uint64_t &bitmaskSizeOut) {
|
||||
struct prelim_drm_i915_debug_eu_control euControl = {};
|
||||
euControl.client_handle = clientHandle;
|
||||
euControl.ci.engine_class = classInstance->engineClass;
|
||||
@@ -1350,17 +1344,8 @@ int DebugSessionLinuxi915::threadControl(const std::vector<EuThread::ThreadId> &
|
||||
}
|
||||
euControl.cmd = command;
|
||||
|
||||
std::unique_ptr<uint8_t[]> bitmask;
|
||||
size_t bitmaskSize = 0;
|
||||
|
||||
if (command == PRELIM_I915_DEBUG_EU_THREADS_CMD_INTERRUPT ||
|
||||
command == PRELIM_I915_DEBUG_EU_THREADS_CMD_RESUME ||
|
||||
command == PRELIM_I915_DEBUG_EU_THREADS_CMD_STOPPED) {
|
||||
l0GfxCoreHelper.getAttentionBitmaskForSingleThreads(threads, hwInfo, bitmask, bitmaskSize);
|
||||
euControl.bitmask_size = static_cast<uint32_t>(bitmaskSize);
|
||||
euControl.bitmask_ptr = reinterpret_cast<uint64_t>(bitmask.get());
|
||||
}
|
||||
|
||||
euControl.bitmask_size = static_cast<uint32_t>(bitmaskSize);
|
||||
euControl.bitmask_ptr = reinterpret_cast<uint64_t>(bitmask.get());
|
||||
if (command == PRELIM_I915_DEBUG_EU_THREADS_CMD_RESUME) {
|
||||
applyResumeWa(bitmask.get(), bitmaskSize);
|
||||
}
|
||||
@@ -1368,25 +1353,8 @@ int DebugSessionLinuxi915::threadControl(const std::vector<EuThread::ThreadId> &
|
||||
printBitmask(bitmask.get(), bitmaskSize);
|
||||
|
||||
auto euControlRetVal = ioctl(PRELIM_I915_DEBUG_IOCTL_EU_CONTROL, &euControl);
|
||||
if (euControlRetVal != 0) {
|
||||
PRINT_DEBUGGER_ERROR_LOG("PRELIM_I915_DEBUG_IOCTL_EU_CONTROL failed: retCode: %d errno = %d command = %d\n", euControlRetVal, errno, command);
|
||||
} else {
|
||||
PRINT_DEBUGGER_INFO_LOG("PRELIM_I915_DEBUG_IOCTL_EU_CONTROL: seqno = %llu command = %u\n", (uint64_t)euControl.seqno, command);
|
||||
}
|
||||
|
||||
if (command == PRELIM_I915_DEBUG_EU_THREADS_CMD_INTERRUPT ||
|
||||
command == PRELIM_I915_DEBUG_EU_THREADS_CMD_INTERRUPT_ALL) {
|
||||
if (euControlRetVal == 0) {
|
||||
euControlInterruptSeqno[tile] = euControl.seqno;
|
||||
} else {
|
||||
euControlInterruptSeqno[tile] = invalidHandle;
|
||||
}
|
||||
}
|
||||
|
||||
if (threadCmd == ThreadControlCmd::stopped) {
|
||||
bitmaskOut = std::move(bitmask);
|
||||
bitmaskSizeOut = euControl.bitmask_size;
|
||||
}
|
||||
seqnoOut = euControl.seqno;
|
||||
bitmaskSizeOut = euControl.bitmask_size;
|
||||
return euControlRetVal;
|
||||
}
|
||||
|
||||
|
||||
@@ -239,7 +239,10 @@ struct DebugSessionLinuxi915 : DebugSessionLinux {
|
||||
ze_result_t writeDefaultMemory(ze_device_thread_t thread, const zet_debug_memory_space_desc_t *desc,
|
||||
size_t size, const void *buffer);
|
||||
|
||||
int threadControl(const std::vector<EuThread::ThreadId> &threads, uint32_t tile, ThreadControlCmd threadCmd, std::unique_ptr<uint8_t[]> &bitmask, size_t &bitmaskSize) override;
|
||||
int euControlIoctl(ThreadControlCmd threadCmd,
|
||||
const NEO::EngineClassInstance *classInstance,
|
||||
std::unique_ptr<uint8_t[]> &bitmask,
|
||||
size_t bitmaskSize, uint64_t &seqnoOut, uint64_t &bitmaskSizeOut) override;
|
||||
uint64_t getContextStateSaveAreaGpuVa(uint64_t memoryHandle) override;
|
||||
size_t getContextStateSaveAreaSize(uint64_t memoryHandle) override;
|
||||
virtual uint64_t getSbaBufferGpuVa(uint64_t memoryHandle);
|
||||
@@ -309,7 +312,6 @@ struct DebugSessionLinuxi915 : DebugSessionLinux {
|
||||
std::atomic<bool> detached{false};
|
||||
|
||||
std::unordered_map<uint64_t, uint32_t> uuidL0CommandQueueHandleToDevice;
|
||||
uint64_t euControlInterruptSeqno[NEO::EngineLimits::maxHandleCount];
|
||||
void readInternalEventsAsync() override;
|
||||
|
||||
bool blockOnFenceMode = false; // false - blocking VM_BIND on CPU - autoack events until last blocking event
|
||||
|
||||
@@ -8,11 +8,13 @@
|
||||
#include "level_zero/tools/source/debug/linux/xe/debug_session.h"
|
||||
|
||||
#include "shared/source/debug_settings/debug_settings_manager.h"
|
||||
#include "shared/source/helpers/hw_info.h"
|
||||
#include "shared/source/memory_manager/memory_manager.h"
|
||||
#include "shared/source/os_interface/linux/drm_debug.h"
|
||||
#include "shared/source/os_interface/linux/sys_calls.h"
|
||||
#include "shared/source/os_interface/linux/xe/ioctl_helper_xe.h"
|
||||
|
||||
#include "level_zero/core/source/gfx_core_helpers/l0_gfx_core_helper.h"
|
||||
#include "level_zero/tools/source/debug/debug_session.h"
|
||||
#include "level_zero/tools/source/debug/linux/drm_helper.h"
|
||||
|
||||
@@ -301,4 +303,43 @@ int DebugSessionLinuxXe::flushVmCache(int vmfd) {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
int DebugSessionLinuxXe::euControlIoctl(ThreadControlCmd threadCmd,
|
||||
const NEO::EngineClassInstance *classInstance,
|
||||
std::unique_ptr<uint8_t[]> &bitmask,
|
||||
size_t bitmaskSize, uint64_t &seqnoOut, uint64_t &bitmaskSizeOut) {
|
||||
struct drm_xe_eudebug_eu_control euControl = {};
|
||||
euControl.client_handle = clientHandle;
|
||||
euControl.ci.engine_class = classInstance->engineClass;
|
||||
euControl.ci.engine_instance = classInstance->engineInstance;
|
||||
euControl.bitmask_size = 0;
|
||||
euControl.bitmask_ptr = 0;
|
||||
|
||||
decltype(drm_xe_eudebug_eu_control::cmd) command = 0;
|
||||
switch (threadCmd) {
|
||||
case ThreadControlCmd::interruptAll:
|
||||
command = DRM_XE_EUDEBUG_EU_CONTROL_CMD_INTERRUPT_ALL;
|
||||
break;
|
||||
case ThreadControlCmd::resume:
|
||||
command = DRM_XE_EUDEBUG_EU_CONTROL_CMD_RESUME;
|
||||
break;
|
||||
case ThreadControlCmd::stopped:
|
||||
command = DRM_XE_EUDEBUG_EU_CONTROL_CMD_STOPPED;
|
||||
break;
|
||||
default:
|
||||
command = 0xFFFFFFFF;
|
||||
break;
|
||||
}
|
||||
euControl.cmd = command;
|
||||
|
||||
euControl.bitmask_size = static_cast<uint32_t>(bitmaskSize);
|
||||
euControl.bitmask_ptr = reinterpret_cast<uint64_t>(bitmask.get());
|
||||
|
||||
printBitmask(bitmask.get(), bitmaskSize);
|
||||
|
||||
auto euControlRetVal = ioctl(DRM_XE_EUDEBUG_IOCTL_EU_CONTROL, &euControl);
|
||||
seqnoOut = euControl.seqno;
|
||||
bitmaskSizeOut = euControl.bitmask_size;
|
||||
return euControlRetVal;
|
||||
}
|
||||
|
||||
} // namespace L0
|
||||
@@ -86,9 +86,11 @@ struct DebugSessionLinuxXe : DebugSessionLinux {
|
||||
uint32_t xeDebuggerVersion = 0;
|
||||
|
||||
protected:
|
||||
int threadControl(const std::vector<EuThread::ThreadId> &threads, uint32_t tile, ThreadControlCmd threadCmd, std::unique_ptr<uint8_t[]> &bitmask, size_t &bitmaskSize) override {
|
||||
return -1;
|
||||
}
|
||||
int euControlIoctl(ThreadControlCmd threadCmd,
|
||||
const NEO::EngineClassInstance *classInstance,
|
||||
std::unique_ptr<uint8_t[]> &bitmask,
|
||||
size_t bitmaskSize, uint64_t &seqnoOut, uint64_t &bitmaskSizeOut) override;
|
||||
|
||||
void startAsyncThread() override;
|
||||
static void *asyncThreadFunction(void *arg);
|
||||
void handleEventsAsync();
|
||||
|
||||
@@ -25,6 +25,7 @@ void DebugApiLinuxXeFixture::setUp(NEO::HardwareInfo *hwInfo) {
|
||||
|
||||
mockDrm = new DrmMockXeDebug(*neoDevice->executionEnvironment->rootDeviceEnvironments[0]);
|
||||
mockDrm->allowDebugAttach = true;
|
||||
mockDrm->queryEngineInfo();
|
||||
|
||||
auto &rootDeviceEnvironment = *neoDevice->executionEnvironment->rootDeviceEnvironments[0];
|
||||
auto gtSystemInfo = &rootDeviceEnvironment.getMutableHardwareInfo()->gtSystemInfo;
|
||||
|
||||
@@ -68,6 +68,23 @@ struct MockIoctlHandlerXe : public L0::ult::MockIoctlHandler {
|
||||
debugEventRetVal = -1;
|
||||
}
|
||||
return debugEventRetVal;
|
||||
} else if ((request == DRM_XE_EUDEBUG_IOCTL_EU_CONTROL) && (arg != nullptr)) {
|
||||
drm_xe_eudebug_eu_control *euControlArg = reinterpret_cast<drm_xe_eudebug_eu_control *>(arg);
|
||||
EuControlArg arg;
|
||||
arg.euControl = *euControlArg;
|
||||
|
||||
euControlArg->seqno = euControlOutputSeqno;
|
||||
|
||||
if (euControlArg->bitmask_size != 0) {
|
||||
arg.euControlBitmaskSize = euControlArg->bitmask_size;
|
||||
arg.euControlBitmask = std::make_unique<uint8_t[]>(arg.euControlBitmaskSize);
|
||||
|
||||
memcpy(arg.euControlBitmask.get(), reinterpret_cast<void *>(euControlArg->bitmask_ptr), arg.euControlBitmaskSize);
|
||||
if (euControlArg->cmd == DRM_XE_EUDEBUG_EU_CONTROL_CMD_STOPPED && euControlArg->bitmask_ptr && outputBitmask.get()) {
|
||||
memcpy_s(reinterpret_cast<uint64_t *>(euControlArg->bitmask_ptr), euControlArg->bitmask_size, outputBitmask.get(), outputBitmaskSize);
|
||||
}
|
||||
}
|
||||
euControlArgs.push_back(std::move(arg));
|
||||
}
|
||||
|
||||
return ioctlRetVal;
|
||||
@@ -82,6 +99,16 @@ struct MockIoctlHandlerXe : public L0::ult::MockIoctlHandler {
|
||||
return fsyncRetVal;
|
||||
}
|
||||
|
||||
struct EuControlArg {
|
||||
EuControlArg() : euControlBitmask(nullptr) {
|
||||
memset(&euControl, 0, sizeof(euControl));
|
||||
}
|
||||
EuControlArg(EuControlArg &&in) : euControl(in.euControl), euControlBitmask(std::move(in.euControlBitmask)), euControlBitmaskSize(in.euControlBitmaskSize){};
|
||||
drm_xe_eudebug_eu_control euControl = {};
|
||||
std::unique_ptr<uint8_t[]> euControlBitmask;
|
||||
size_t euControlBitmaskSize = 0;
|
||||
};
|
||||
|
||||
drm_xe_eudebug_event debugEventInput = {};
|
||||
|
||||
int ioctlRetVal = 0;
|
||||
@@ -90,21 +117,32 @@ struct MockIoctlHandlerXe : public L0::ult::MockIoctlHandler {
|
||||
int fsyncCalled = 0;
|
||||
int fsyncRetVal = 0;
|
||||
int numFsyncToSucceed = 100;
|
||||
uint64_t euControlOutputSeqno = 10;
|
||||
std::vector<EuControlArg> euControlArgs;
|
||||
std::unique_ptr<uint8_t[]> outputBitmask;
|
||||
size_t outputBitmaskSize = 0;
|
||||
};
|
||||
|
||||
struct MockDebugSessionLinuxXe : public L0::DebugSessionLinuxXe {
|
||||
using L0::DebugSessionImp::allThreads;
|
||||
using L0::DebugSessionImp::apiEvents;
|
||||
using L0::DebugSessionImp::stateSaveAreaHeader;
|
||||
using L0::DebugSessionLinuxXe::asyncThread;
|
||||
using L0::DebugSessionLinuxXe::asyncThreadFunction;
|
||||
using L0::DebugSessionLinuxXe::checkStoppedThreadsAndGenerateEvents;
|
||||
using L0::DebugSessionLinuxXe::clientHandleClosed;
|
||||
using L0::DebugSessionLinuxXe::clientHandleToConnection;
|
||||
using L0::DebugSessionLinuxXe::euControlInterruptSeqno;
|
||||
using L0::DebugSessionLinuxXe::handleEvent;
|
||||
using L0::DebugSessionLinuxXe::internalEventQueue;
|
||||
using L0::DebugSessionLinuxXe::internalEventThread;
|
||||
using L0::DebugSessionLinuxXe::invalidClientHandle;
|
||||
using L0::DebugSessionLinuxXe::ioctlHandler;
|
||||
using L0::DebugSessionLinuxXe::readEventImp;
|
||||
using L0::DebugSessionLinuxXe::readInternalEventsAsync;
|
||||
using L0::DebugSessionLinuxXe::startAsyncThread;
|
||||
using L0::DebugSessionLinuxXe::threadControl;
|
||||
using L0::DebugSessionLinuxXe::ThreadControlCmd;
|
||||
|
||||
MockDebugSessionLinuxXe(const zet_debug_config_t &config, L0::Device *device, int debugFd, void *params) : DebugSessionLinuxXe(config, device, debugFd, params) {
|
||||
clientHandleToConnection[mockClientHandle].reset(new ClientConnection);
|
||||
@@ -140,6 +178,7 @@ struct MockDebugSessionLinuxXe : public L0::DebugSessionLinuxXe {
|
||||
std::atomic<int> getInternalEventCounter = 0;
|
||||
ze_result_t initializeRetVal = ZE_RESULT_FORCE_UINT32;
|
||||
static constexpr uint64_t mockClientHandle = 1;
|
||||
std::unordered_map<uint64_t, uint8_t> stoppedThreads;
|
||||
};
|
||||
|
||||
struct MockAsyncThreadDebugSessionLinuxXe : public MockDebugSessionLinuxXe {
|
||||
|
||||
@@ -140,19 +140,6 @@ TEST(IoctlHandler, GivenHandlerWhenIoctlFailsWithEBUSYThenIoctlIsAgain) {
|
||||
|
||||
using DebugApiLinuxTestXe = Test<DebugApiLinuxXeFixture>;
|
||||
|
||||
TEST_F(DebugApiLinuxTestXe, WhenCallingThreadControlForInterruptThenErrorIsReturned) {
|
||||
zet_debug_config_t config = {};
|
||||
config.pid = 0x1234;
|
||||
|
||||
auto session = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
|
||||
|
||||
EXPECT_NE(nullptr, session);
|
||||
std::vector<EuThread::ThreadId> threads({});
|
||||
std::unique_ptr<uint8_t[]> bitmaskOut;
|
||||
size_t bitmaskSizeOut = 0;
|
||||
EXPECT_EQ(-1, session->threadControl(threads, 0, MockDebugSessionLinuxXe::ThreadControlCmd::interrupt, bitmaskOut, bitmaskSizeOut));
|
||||
}
|
||||
|
||||
TEST_F(DebugApiLinuxTestXe, GivenDebugSessionWhenCallingPollThenDefaultHandlerRedirectsToSysCall) {
|
||||
zet_debug_config_t config = {};
|
||||
config.pid = 0x1234;
|
||||
@@ -906,5 +893,148 @@ TEST_F(DebugApiLinuxTestXe, WhenCallingReadOrWriteGpuMemoryAndFsyncFailsThenErro
|
||||
EXPECT_EQ(handler->fsyncCalled, 6);
|
||||
}
|
||||
|
||||
TEST_F(DebugApiLinuxTestXe, WhenCallingThreadControlForInterruptThenProperIoctlsIsCalled) {
|
||||
zet_debug_config_t config = {};
|
||||
config.pid = 0x1234;
|
||||
|
||||
auto sessionMock = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
|
||||
ASSERT_NE(nullptr, sessionMock);
|
||||
|
||||
auto handler = new MockIoctlHandlerXe;
|
||||
sessionMock->ioctlHandler.reset(handler);
|
||||
std::vector<EuThread::ThreadId> threads({});
|
||||
|
||||
std::unique_ptr<uint8_t[]> bitmaskOut;
|
||||
size_t bitmaskSizeOut = 0;
|
||||
|
||||
auto result = sessionMock->threadControl(threads, 0, MockDebugSessionLinuxXe::ThreadControlCmd::interrupt, bitmaskOut, bitmaskSizeOut);
|
||||
EXPECT_EQ(result, ZE_RESULT_SUCCESS);
|
||||
|
||||
EXPECT_EQ(1, handler->ioctlCalled);
|
||||
EXPECT_EQ(0xFFFFFFFF, handler->euControlArgs[0].euControl.cmd);
|
||||
EXPECT_NE(0u, handler->euControlArgs[0].euControl.bitmask_size);
|
||||
auto bitMaskPtrToCheck = handler->euControlArgs[0].euControl.bitmask_ptr;
|
||||
EXPECT_NE(0u, bitMaskPtrToCheck);
|
||||
EXPECT_EQ(handler->euControlOutputSeqno, sessionMock->euControlInterruptSeqno[0]);
|
||||
|
||||
EXPECT_EQ(0u, bitmaskSizeOut);
|
||||
EXPECT_EQ(nullptr, bitmaskOut.get());
|
||||
|
||||
handler->euControlOutputSeqno = handler->euControlOutputSeqno + 3;
|
||||
handler->ioctlCalled = 0;
|
||||
result = sessionMock->threadControl(threads, 0, MockDebugSessionLinuxXe::ThreadControlCmd::interruptAll, bitmaskOut, bitmaskSizeOut);
|
||||
EXPECT_EQ(result, ZE_RESULT_SUCCESS);
|
||||
|
||||
EXPECT_EQ(1, handler->ioctlCalled);
|
||||
EXPECT_EQ(uint32_t(DRM_XE_EUDEBUG_EU_CONTROL_CMD_INTERRUPT_ALL), handler->euControlArgs[1].euControl.cmd);
|
||||
EXPECT_EQ(0u, handler->euControlArgs[1].euControl.bitmask_size);
|
||||
auto bitMaskPtrToCheck1 = handler->euControlArgs[1].euControl.bitmask_ptr;
|
||||
EXPECT_EQ(0u, bitMaskPtrToCheck1);
|
||||
EXPECT_EQ(handler->euControlOutputSeqno, sessionMock->euControlInterruptSeqno[0]);
|
||||
|
||||
EXPECT_EQ(0u, bitmaskSizeOut);
|
||||
EXPECT_EQ(nullptr, bitmaskOut.get());
|
||||
}
|
||||
|
||||
TEST_F(DebugApiLinuxTestXe, GivenErrorFromIoctlWhenCallingThreadControlForInterruptThenSeqnoIsNotUpdated) {
|
||||
zet_debug_config_t config = {};
|
||||
config.pid = 0x1234;
|
||||
|
||||
auto sessionMock = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
|
||||
ASSERT_NE(nullptr, sessionMock);
|
||||
|
||||
auto handler = new MockIoctlHandlerXe;
|
||||
sessionMock->ioctlHandler.reset(handler);
|
||||
std::vector<EuThread::ThreadId> threads({});
|
||||
|
||||
std::unique_ptr<uint8_t[]> bitmaskOut;
|
||||
size_t bitmaskSizeOut = 0;
|
||||
|
||||
handler->ioctlRetVal = -1;
|
||||
|
||||
auto result = sessionMock->threadControl(threads, 0, MockDebugSessionLinuxXe::ThreadControlCmd::interruptAll, bitmaskOut, bitmaskSizeOut);
|
||||
EXPECT_NE(0, result);
|
||||
|
||||
EXPECT_EQ(1, handler->ioctlCalled);
|
||||
EXPECT_EQ(uint32_t(DRM_XE_EUDEBUG_EU_CONTROL_CMD_INTERRUPT_ALL), handler->euControlArgs[0].euControl.cmd);
|
||||
EXPECT_NE(handler->euControlOutputSeqno, sessionMock->euControlInterruptSeqno[0]);
|
||||
}
|
||||
|
||||
TEST_F(DebugApiLinuxTestXe, WhenCallingThreadControlForResumeThenProperIoctlsIsCalled) {
|
||||
zet_debug_config_t config = {};
|
||||
config.pid = 0x1234;
|
||||
|
||||
auto sessionMock = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
|
||||
ASSERT_NE(nullptr, sessionMock);
|
||||
|
||||
auto handler = new MockIoctlHandlerXe;
|
||||
sessionMock->ioctlHandler.reset(handler);
|
||||
std::vector<EuThread::ThreadId> threads({});
|
||||
|
||||
std::unique_ptr<uint8_t[]> bitmaskOut;
|
||||
size_t bitmaskSizeOut = 0;
|
||||
|
||||
auto result = sessionMock->threadControl(threads, 0, MockDebugSessionLinuxXe::ThreadControlCmd::resume, bitmaskOut, bitmaskSizeOut);
|
||||
EXPECT_EQ(result, ZE_RESULT_SUCCESS);
|
||||
|
||||
EXPECT_EQ(1, handler->ioctlCalled);
|
||||
EXPECT_EQ(uint32_t(DRM_XE_EUDEBUG_EU_CONTROL_CMD_RESUME), handler->euControlArgs[0].euControl.cmd);
|
||||
EXPECT_NE(0u, handler->euControlArgs[0].euControl.bitmask_size);
|
||||
auto bitMaskPtrToCheck = handler->euControlArgs[0].euControl.bitmask_ptr;
|
||||
EXPECT_NE(0u, bitMaskPtrToCheck);
|
||||
|
||||
EXPECT_EQ(0u, bitmaskSizeOut);
|
||||
EXPECT_EQ(nullptr, bitmaskOut.get());
|
||||
}
|
||||
|
||||
TEST_F(DebugApiLinuxTestXe, GivenNoAttentionBitsWhenMultipleThreadsPassedToCheckStoppedThreadsAndGenerateEventsThenThreadsStateNotCheckedAndEventsNotGenerated) {
|
||||
zet_debug_config_t config = {};
|
||||
config.pid = 0x1234;
|
||||
|
||||
auto sessionMock = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
|
||||
ASSERT_NE(nullptr, sessionMock);
|
||||
|
||||
auto handler = new MockIoctlHandlerXe;
|
||||
sessionMock->ioctlHandler.reset(handler);
|
||||
EuThread::ThreadId thread = {0, 0, 0, 0, 0};
|
||||
EuThread::ThreadId thread1 = {0, 0, 0, 0, 1};
|
||||
EuThread::ThreadId thread2 = {0, 0, 0, 0, 2};
|
||||
const auto memoryHandle = 1u;
|
||||
|
||||
std::vector<EuThread::ThreadId> threads;
|
||||
threads.push_back(thread);
|
||||
threads.push_back(thread1);
|
||||
|
||||
sessionMock->allThreads[thread.packed]->verifyStopped(1);
|
||||
sessionMock->allThreads[thread.packed]->stopThread(memoryHandle);
|
||||
sessionMock->allThreads[thread.packed]->reportAsStopped();
|
||||
sessionMock->stoppedThreads[thread.packed] = 1; // previously stopped
|
||||
sessionMock->stoppedThreads[thread1.packed] = 3; // newly stopped
|
||||
sessionMock->stoppedThreads[thread2.packed] = 3; // newly stopped
|
||||
|
||||
std::unique_ptr<uint8_t[]> bitmask;
|
||||
size_t bitmaskSize = 0;
|
||||
auto &hwInfo = neoDevice->getHardwareInfo();
|
||||
auto &l0GfxCoreHelper = neoDevice->getRootDeviceEnvironment().getHelper<L0GfxCoreHelper>();
|
||||
l0GfxCoreHelper.getAttentionBitmaskForSingleThreads(threads, hwInfo, bitmask, bitmaskSize);
|
||||
memset(bitmask.get(), 0, bitmaskSize);
|
||||
|
||||
handler->outputBitmaskSize = bitmaskSize;
|
||||
handler->outputBitmask = std::move(bitmask);
|
||||
|
||||
sessionMock->checkStoppedThreadsAndGenerateEvents(threads, memoryHandle, 0);
|
||||
|
||||
EXPECT_EQ(1, handler->ioctlCalled);
|
||||
EXPECT_EQ(1u, handler->euControlArgs.size());
|
||||
EXPECT_EQ(2u, sessionMock->numThreadsPassedToThreadControl);
|
||||
EXPECT_EQ(uint32_t(DRM_XE_EUDEBUG_EU_CONTROL_CMD_STOPPED), handler->euControlArgs[0].euControl.cmd);
|
||||
|
||||
EXPECT_TRUE(sessionMock->allThreads[thread.packed]->isStopped());
|
||||
EXPECT_FALSE(sessionMock->allThreads[thread1.packed]->isStopped());
|
||||
EXPECT_FALSE(sessionMock->allThreads[thread2.packed]->isStopped());
|
||||
|
||||
EXPECT_EQ(0u, sessionMock->apiEvents.size());
|
||||
}
|
||||
|
||||
} // namespace ult
|
||||
} // namespace L0
|
||||
@@ -42,7 +42,9 @@ inline constexpr uint32_t testValueGemCreate = 0x8273;
|
||||
|
||||
class DrmMockXeDebug : public DrmMockCustom {
|
||||
public:
|
||||
DrmMockXeDebug(RootDeviceEnvironment &rootDeviceEnvironment) : DrmMockCustom(rootDeviceEnvironment){};
|
||||
DrmMockXeDebug(RootDeviceEnvironment &rootDeviceEnvironment) : DrmMockCustom(rootDeviceEnvironment) {
|
||||
this->ioctlHelper = std::make_unique<IoctlHelperXe>(*this);
|
||||
};
|
||||
|
||||
int getErrno() override {
|
||||
if (baseErrno) {
|
||||
|
||||
Reference in New Issue
Block a user