feature: Implement VM_BIND EU debug event for XE

Related-To: NEO-8407
Signed-off-by: Jitendra Sharma <jitendra.sharma@intel.com>
This commit is contained in:
Jitendra Sharma
2024-03-22 12:13:53 +00:00
committed by Compute-Runtime-Automation
parent e8983f5274
commit b8c27ddb20
8 changed files with 752 additions and 74 deletions

View File

@@ -104,7 +104,7 @@ struct DebugSessionLinux : DebugSessionImp {
};
struct IsaAllocation {
BindInfo bindInfo;
uint64_t elfUuidHandle;
uint64_t elfHandle;
uint64_t vmHandle;
bool tileInstanced = false;
bool perKernelModule = true;
@@ -171,6 +171,28 @@ struct DebugSessionLinux : DebugSessionImp {
uint8_t *bitmask;
};
std::vector<std::pair<zet_debug_event_t, uint64_t>> eventsToAck; // debug event, handle to module
void enqueueApiEvent(zet_debug_event_t &debugEvent) override {
pushApiEvent(debugEvent);
}
void pushApiEvent(zet_debug_event_t &debugEvent) {
return pushApiEvent(debugEvent, invalidHandle);
}
void pushApiEvent(zet_debug_event_t &debugEvent, uint64_t moduleHandle) {
std::unique_lock<std::mutex> lock(asyncThreadMutex);
if (moduleHandle != invalidHandle && (debugEvent.flags & ZET_DEBUG_EVENT_FLAG_NEED_ACK)) {
eventsToAck.push_back(
std::pair<zet_debug_event_t, uint64_t>(debugEvent, moduleHandle));
}
apiEvents.push(debugEvent);
apiEventCondition.notify_all();
}
void updateStoppedThreadsAndCheckTriggerEvents(AttentionEventFields &attention, uint32_t tileIndex, std::vector<EuThread::ThreadId> &threadsWithAttention);
virtual void updateContextAndLrcHandlesForThreadsWithAttention(EuThread::ThreadId threadId, AttentionEventFields &attention) = 0;
virtual uint64_t getVmHandleFromClientAndlrcHandle(uint64_t clientHandle, uint64_t lrcHandle) = 0;

View File

@@ -672,7 +672,7 @@ bool DebugSessionLinuxi915::handleVmBindEvent(prelim_drm_i915_debug_event_vm_bin
auto isa = std::make_unique<IsaAllocation>();
isa->bindInfo = {vmBind->va_start, vmBind->va_length};
isa->vmHandle = vmHandle;
isa->elfUuidHandle = invalidHandle;
isa->elfHandle = invalidHandle;
isa->moduleBegin = 0;
isa->moduleEnd = 0;
isa->tileInstanced = tileInstanced;
@@ -681,7 +681,7 @@ bool DebugSessionLinuxi915::handleVmBindEvent(prelim_drm_i915_debug_event_vm_bin
for (index = 1; index < vmBind->num_uuids; index++) {
if (connection->uuidMap[vmBind->uuids[index]].classIndex == NEO::DrmResourceClass::elf) {
isa->elfUuidHandle = vmBind->uuids[index];
isa->elfHandle = vmBind->uuids[index];
if (!perKernelModules) {
auto &module = connection->uuidToModule[vmBind->uuids[moduleUUIDindex]];
@@ -693,10 +693,10 @@ bool DebugSessionLinuxi915::handleVmBindEvent(prelim_drm_i915_debug_event_vm_bin
}
}
if (isa->elfUuidHandle != invalidHandle) {
isa->moduleBegin = connection->uuidMap[isa->elfUuidHandle].ptr;
isa->moduleEnd = isa->moduleBegin + connection->uuidMap[isa->elfUuidHandle].dataSize;
elfMap[isa->moduleBegin] = isa->elfUuidHandle;
if (isa->elfHandle != invalidHandle) {
isa->moduleBegin = connection->uuidMap[isa->elfHandle].ptr;
isa->moduleEnd = isa->moduleBegin + connection->uuidMap[isa->elfHandle].dataSize;
elfMap[isa->moduleBegin] = isa->elfHandle;
} else {
PRINT_DEBUGGER_ERROR_LOG("No ELF provided by application\n", "");
}

View File

@@ -114,27 +114,6 @@ struct DebugSessionLinuxi915 : DebugSessionLinux {
ze_result_t readEventImp(prelim_drm_i915_debug_event *drmDebugEvent);
void enqueueApiEvent(zet_debug_event_t &debugEvent) override {
pushApiEvent(debugEvent);
}
void pushApiEvent(zet_debug_event_t &debugEvent) {
return pushApiEvent(debugEvent, invalidHandle);
}
void pushApiEvent(zet_debug_event_t &debugEvent, uint64_t moduleUuidHandle) {
std::unique_lock<std::mutex> lock(asyncThreadMutex);
if (moduleUuidHandle != invalidHandle && (debugEvent.flags & ZET_DEBUG_EVENT_FLAG_NEED_ACK)) {
eventsToAck.push_back(
std::pair<zet_debug_event_t, uint64_t>(debugEvent, moduleUuidHandle));
}
apiEvents.push(debugEvent);
apiEventCondition.notify_all();
}
MOCKABLE_VIRTUAL void createTileSessionsIfEnabled();
MOCKABLE_VIRTUAL TileDebugSessionLinuxi915 *createTileSession(const zet_debug_config_t &config, Device *device, DebugSessionImp *rootDebugSession);
@@ -234,7 +213,6 @@ struct DebugSessionLinuxi915 : DebugSessionLinux {
return allInstancesRemoved;
}
std::vector<std::pair<zet_debug_event_t, uint64_t>> eventsToAck; // debug event, uuid handle to module
std::vector<std::unique_ptr<uint64_t[]>> pendingVmBindEvents;
uint32_t i915DebuggerVersion = 0;

View File

@@ -8,6 +8,7 @@
#include "level_zero/tools/source/debug/linux/xe/debug_session.h"
#include "shared/source/debug_settings/debug_settings_manager.h"
#include "shared/source/gmm_helper/gmm_helper.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"
@@ -170,19 +171,13 @@ ze_result_t DebugSessionLinuxXe::readEventImp(drm_xe_eudebug_event *drmDebugEven
if (ret != 0) {
PRINT_DEBUGGER_ERROR_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT failed: retCode: %d errno = %d\n", ret, errno);
return ZE_RESULT_NOT_READY;
} else if (drmDebugEvent->flags & ~static_cast<uint32_t>(DRM_XE_EUDEBUG_EVENT_CREATE | DRM_XE_EUDEBUG_EVENT_DESTROY | DRM_XE_EUDEBUG_EVENT_STATE_CHANGE)) {
} else if (drmDebugEvent->flags & ~static_cast<uint32_t>(DRM_XE_EUDEBUG_EVENT_CREATE | DRM_XE_EUDEBUG_EVENT_DESTROY | DRM_XE_EUDEBUG_EVENT_STATE_CHANGE | DRM_XE_EUDEBUG_EVENT_NEED_ACK)) {
PRINT_DEBUGGER_ERROR_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT unsupported flag = %d\n", (int)drmDebugEvent->flags);
return ZE_RESULT_ERROR_UNKNOWN;
}
return ZE_RESULT_SUCCESS;
}
void DebugSessionLinuxXe::pushApiEvent(zet_debug_event_t &debugEvent) {
std::unique_lock<std::mutex> lock(asyncThreadMutex);
apiEvents.push(debugEvent);
apiEventCondition.notify_all();
}
bool DebugSessionLinuxXe::closeConnection() {
closeInternalEventsThread();
return closeFd();
@@ -208,16 +203,16 @@ void DebugSessionLinuxXe::handleEvent(drm_xe_eudebug_event *event) {
clientHandleClosed = clientEvent->client_handle;
}
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_OPEN flags = %u len = %lu client.handle = %llu\n",
(uint16_t)event->flags, (uint32_t)event->len, (uint64_t)clientEvent->client_handle);
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_OPEN client.handle = %llu\n",
(uint64_t)clientEvent->client_handle);
} break;
case DRM_XE_EUDEBUG_EVENT_VM: {
drm_xe_eudebug_event_vm *vm = reinterpret_cast<drm_xe_eudebug_event_vm *>(event);
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_VM flags = %u size = %lu client_handle = %llu vm_handle = %llu\n",
(uint16_t)event->flags, (uint32_t)event->len, (uint64_t)vm->client_handle, (uint64_t)vm->vm_handle);
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_VM client_handle = %llu vm_handle = %llu\n",
(uint64_t)vm->client_handle, (uint64_t)vm->vm_handle);
if (event->flags & DRM_XE_EUDEBUG_EVENT_CREATE) {
UNRECOVERABLE_IF(clientHandleToConnection.find(vm->client_handle) == clientHandleToConnection.end());
@@ -275,38 +270,224 @@ void DebugSessionLinuxXe::handleEvent(drm_xe_eudebug_event *event) {
}
}
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_EXEC_QUEUE flags = %u len = %lu client_handle = %llu\
vm_handle = %llu exec_queue_handle = %llu engine_class = %u\n",
(uint16_t)event->flags, (uint32_t)event->len, (uint64_t)execQueue->client_handle, (uint64_t)execQueue->vm_handle,
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_EXEC_QUEUE client_handle = %llu vm_handle = %llu exec_queue_handle = %llu engine_class = %u\n",
(uint64_t)execQueue->client_handle, (uint64_t)execQueue->vm_handle,
(uint64_t)execQueue->exec_queue_handle, (uint16_t)execQueue->engine_class);
} break;
case DRM_XE_EUDEBUG_EVENT_EU_ATTENTION: {
drm_xe_eudebug_event_eu_attention *attention = reinterpret_cast<drm_xe_eudebug_event_eu_attention *>(event);
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_EU_ATTENTION flags = %d, seqno = %llu, len = %lu"
" client_handle = %llu flags = %llu bitmask_size = %lu exec_queue_handle = %llu lrc_handle = %llu\n",
(int)attention->base.flags, (uint64_t)attention->base.seqno, (uint32_t)attention->base.len,
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_EU_ATTENTION client_handle = %llu flags = %llu bitmask_size = %lu exec_queue_handle = %llu lrc_handle = %llu\n",
(uint64_t)attention->client_handle, (uint64_t)attention->flags,
(uint32_t)attention->bitmask_size, uint64_t(attention->exec_queue_handle), uint64_t(attention->lrc_handle));
handleAttentionEvent(attention);
} break;
case DRM_XE_EUDEBUG_EVENT_VM_BIND: {
drm_xe_eudebug_event_vm_bind *vmBind = reinterpret_cast<drm_xe_eudebug_event_vm_bind *>(event);
UNRECOVERABLE_IF(clientHandleToConnection.find(vmBind->client_handle) == clientHandleToConnection.end());
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_VM_BIND client_handle = %llu vm_handle = %llu num_binds = %llu vmBindflag=%lu\n",
static_cast<uint64_t>(vmBind->client_handle), static_cast<uint64_t>(vmBind->vm_handle),
static_cast<uint64_t>(vmBind->num_binds), static_cast<uint32_t>(vmBind->flags));
auto &connection = clientHandleToConnection[vmBind->client_handle];
UNRECOVERABLE_IF(connection->vmBindMap.find(vmBind->base.seqno) != connection->vmBindMap.end());
auto &vmBindData = connection->vmBindMap[vmBind->base.seqno];
vmBindData.vmBind = *vmBind;
vmBindData.pendingNumBinds = vmBind->num_binds;
} break;
case DRM_XE_EUDEBUG_EVENT_VM_BIND_OP: {
drm_xe_eudebug_event_vm_bind_op *vmBindOp = reinterpret_cast<drm_xe_eudebug_event_vm_bind_op *>(event);
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: drm_xe_eudebug_event_vm_bind_op vm_bind_ref_seqno = %llu num_extensions = %llu addr = %llu range = %llu\n",
static_cast<uint64_t>(vmBindOp->vm_bind_ref_seqno), static_cast<uint64_t>(vmBindOp->num_extensions),
static_cast<uint64_t>(vmBindOp->addr), static_cast<uint64_t>(vmBindOp->range));
auto &vmBindMap = clientHandleToConnection[clientHandle]->vmBindMap;
UNRECOVERABLE_IF(vmBindMap.find(vmBindOp->vm_bind_ref_seqno) == vmBindMap.end());
auto &vmBindData = vmBindMap[vmBindOp->vm_bind_ref_seqno];
UNRECOVERABLE_IF(!vmBindData.pendingNumBinds);
auto &vmBindOpData = vmBindData.vmBindOpMap[vmBindOp->base.seqno];
vmBindOpData.pendingNumExtensions = vmBindOp->num_extensions;
vmBindOpData.vmBindOp = *vmBindOp;
vmBindData.pendingNumBinds--;
clientHandleToConnection[clientHandle]->vmBindIdentifierMap[vmBindOp->base.seqno] = vmBindOp->vm_bind_ref_seqno;
handleVmBindWithoutUfence(vmBindData, vmBindOpData);
} break;
case DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE: {
drm_xe_eudebug_event_vm_bind_ufence *vmBindUfence = reinterpret_cast<drm_xe_eudebug_event_vm_bind_ufence *>(event);
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE vm_bind_ref_seqno = %llu\n",
static_cast<uint64_t>(vmBindUfence->vm_bind_ref_seqno));
auto &vmBindMap = clientHandleToConnection[clientHandle]->vmBindMap;
UNRECOVERABLE_IF(vmBindMap.find(vmBindUfence->vm_bind_ref_seqno) == vmBindMap.end());
uint32_t uFenceRequired = vmBindMap[vmBindUfence->vm_bind_ref_seqno].vmBind.flags & DRM_XE_EUDEBUG_EVENT_VM_BIND_FLAG_UFENCE;
UNRECOVERABLE_IF(!uFenceRequired);
UNRECOVERABLE_IF(vmBindMap[vmBindUfence->vm_bind_ref_seqno].pendingNumBinds);
vmBindMap[vmBindUfence->vm_bind_ref_seqno].vmBindUfence = *vmBindUfence;
handleVmBind(vmBindMap[vmBindUfence->vm_bind_ref_seqno]);
} break;
case DRM_XE_EUDEBUG_EVENT_METADATA: {
drm_xe_eudebug_event_metadata *metaData = reinterpret_cast<drm_xe_eudebug_event_metadata *>(event);
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_METADATA flags = %d len = %llu client_handle = %llu metadata_handle = %llu type = %llu len = %llu\n",
(int)event->flags, (uint64_t)event->len, (uint64_t)metaData->client_handle, (uint64_t)metaData->metadata_handle, (uint64_t)metaData->type, (uint64_t)metaData->len);
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_METADATA client_handle = %llu metadata_handle = %llu type = %llu len = %llu\n",
(uint64_t)metaData->client_handle, (uint64_t)metaData->metadata_handle, (uint64_t)metaData->type, (uint64_t)metaData->len);
handleMetadataEvent(metaData);
} break;
case DRM_XE_EUDEBUG_EVENT_VM_BIND_OP_METADATA: {
drm_xe_eudebug_event_vm_bind_op_metadata *vmBindOpMetadata = reinterpret_cast<drm_xe_eudebug_event_vm_bind_op_metadata *>(event);
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: DRM_XE_EUDEBUG_EVENT_VM_BIND_OP_METADATA vm_bind_op_ref_seqno = %llu metadata_handle = %llu metadata_cookie = %llu\n",
static_cast<uint64_t>(vmBindOpMetadata->vm_bind_op_ref_seqno), static_cast<uint64_t>(vmBindOpMetadata->metadata_handle),
static_cast<uint64_t>(vmBindOpMetadata->metadata_cookie));
auto &vmBindMap = clientHandleToConnection[clientHandle]->vmBindMap;
auto &vmBindIdentifierMap = clientHandleToConnection[clientHandle]->vmBindIdentifierMap;
UNRECOVERABLE_IF(vmBindIdentifierMap.find(vmBindOpMetadata->vm_bind_op_ref_seqno) == vmBindIdentifierMap.end());
VmBindSeqNo vmBindSeqNo = vmBindIdentifierMap[vmBindOpMetadata->vm_bind_op_ref_seqno];
UNRECOVERABLE_IF(vmBindMap.find(vmBindSeqNo) == vmBindMap.end());
auto &vmBindOpData = vmBindMap[vmBindSeqNo].vmBindOpMap[vmBindOpMetadata->vm_bind_op_ref_seqno];
UNRECOVERABLE_IF(!vmBindOpData.pendingNumExtensions);
vmBindOpData.vmBindOpMetadataVec.push_back(*vmBindOpMetadata);
vmBindOpData.pendingNumExtensions--;
handleVmBindWithoutUfence(vmBindMap[vmBindSeqNo], vmBindOpData);
} break;
default:
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_READ_EVENT type: UNHANDLED %u flags = %u len = %lu\n", (uint16_t)event->type, (uint16_t)event->flags, (uint32_t)event->len);
break;
}
}
void DebugSessionLinuxXe::handleVmBindWithoutUfence(VmBindData &vmBindData, VmBindOpData &vmBindOpData) {
uint32_t uFenceRequired = vmBindData.vmBind.flags & DRM_XE_EUDEBUG_EVENT_VM_BIND_FLAG_UFENCE;
if (uFenceRequired) {
return;
}
if (vmBindData.pendingNumBinds || vmBindOpData.pendingNumExtensions) {
return;
}
handleVmBind(vmBindData);
}
void DebugSessionLinuxXe::handleVmBind(VmBindData &vmBindData) {
bool shouldAckEvent = vmBindData.vmBind.flags & DRM_XE_EUDEBUG_EVENT_VM_BIND_FLAG_UFENCE;
auto connection = clientHandleToConnection[clientHandle].get();
for (auto &vmBindOpData : vmBindData.vmBindOpMap) {
UNRECOVERABLE_IF(vmBindOpData.second.pendingNumExtensions);
for (const auto &vmBindOpMetadata : vmBindOpData.second.vmBindOpMetadataVec) {
auto &vmBindOp = vmBindOpData.second.vmBindOp;
auto &metaDataEntry = connection->metaDataMap[vmBindOpMetadata.metadata_handle];
if (vmBindOp.base.flags & DRM_XE_EUDEBUG_EVENT_CREATE) {
{
std::lock_guard<std::mutex> lock(asyncThreadMutex);
if (metaDataEntry.metadata.type == WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_SBA_AREA) {
connection->vmToStateBaseAreaBindInfo[vmBindData.vmBind.vm_handle] = {vmBindOp.addr, vmBindOp.range};
}
if (metaDataEntry.metadata.type == WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_SIP_AREA) {
connection->vmToContextStateSaveAreaBindInfo[vmBindData.vmBind.vm_handle] = {vmBindOp.addr, vmBindOp.range};
}
if (metaDataEntry.metadata.type == WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_MODULE_AREA) {
connection->vmToModuleDebugAreaBindInfo[vmBindData.vmBind.vm_handle] = {vmBindOp.addr, vmBindOp.range};
}
}
if (metaDataEntry.metadata.type == DRM_XE_DEBUG_METADATA_ELF_BINARY) {
if (connection->isaMap[0].find(vmBindOp.addr) == connection->isaMap[0].end()) {
auto &isaMap = connection->isaMap[0];
auto &elfMap = connection->elfMap;
auto isa = std::make_unique<IsaAllocation>();
isa->bindInfo = {vmBindOp.addr, vmBindOp.range};
isa->vmHandle = vmBindData.vmBind.vm_handle;
isa->elfHandle = vmBindOpMetadata.metadata_handle;
isa->moduleBegin = reinterpret_cast<uint64_t>(metaDataEntry.data.get());
isa->moduleEnd = isa->moduleBegin + metaDataEntry.metadata.len;
isa->tileInstanced = false;
isa->perKernelModule = false;
elfMap[isa->moduleBegin] = isa->elfHandle;
isaMap[vmBindOp.addr] = std::move(isa);
isaMap[vmBindOp.addr]->moduleLoadEventAck = true;
}
}
if (metaDataEntry.metadata.type == DRM_XE_DEBUG_METADATA_PROGRAM_MODULE) {
auto &module = connection->metaDataToModule[vmBindOpMetadata.metadata_handle];
uint64_t loadAddress = 0;
module.segmentVmBindCounter[0]++;
DEBUG_BREAK_IF(module.loadAddresses[0].size() > module.segmentCount);
bool canTriggerEvent = module.loadAddresses[0].size() == (module.segmentCount - 1);
module.loadAddresses[0].insert(vmBindOp.addr);
if (canTriggerEvent && module.loadAddresses[0].size() == module.segmentCount) {
auto gmmHelper = connectedDevice->getNEODevice()->getGmmHelper();
loadAddress = gmmHelper->canonize(*std::min_element(module.loadAddresses[0].begin(), module.loadAddresses[0].end()));
PRINT_DEBUGGER_INFO_LOG("Zebin module loaded at: %p, with %u isa allocations", (void *)loadAddress, module.segmentCount);
zet_debug_event_t debugEvent = {};
debugEvent.type = ZET_DEBUG_EVENT_TYPE_MODULE_LOAD;
debugEvent.info.module.format = ZET_MODULE_DEBUG_INFO_FORMAT_ELF_DWARF;
debugEvent.info.module.load = loadAddress;
debugEvent.info.module.moduleBegin = reinterpret_cast<uint64_t>(metaDataEntry.data.get());
debugEvent.info.module.moduleEnd = reinterpret_cast<uint64_t>(metaDataEntry.data.get()) + metaDataEntry.metadata.len;
debugEvent.flags = ZET_DEBUG_EVENT_FLAG_NEED_ACK;
pushApiEvent(debugEvent, metaDataEntry.metadata.metadata_handle);
{
std::lock_guard<std::mutex> lock(asyncThreadMutex);
if (vmBindData.vmBind.flags & DRM_XE_EUDEBUG_EVENT_VM_BIND_FLAG_UFENCE) {
if (vmBindData.vmBindUfence.base.flags & DRM_XE_EUDEBUG_EVENT_NEED_ACK) {
EventToAck ackEvent(vmBindData.vmBindUfence.base.seqno, vmBindData.vmBindUfence.base.type);
module.ackEvents[0].push_back(ackEvent);
shouldAckEvent = false;
}
}
}
}
}
}
bool destroy = vmBindOp.base.flags & DRM_XE_EUDEBUG_EVENT_DESTROY;
if (destroy && metaDataEntry.metadata.type == DRM_XE_DEBUG_METADATA_PROGRAM_MODULE) {
auto &module = connection->metaDataToModule[vmBindOpMetadata.metadata_handle];
module.segmentVmBindCounter[0]--;
if (module.segmentVmBindCounter[0] == 0) {
zet_debug_event_t debugEvent = {};
auto gmmHelper = connectedDevice->getNEODevice()->getGmmHelper();
auto loadAddress = gmmHelper->canonize(*std::min_element(module.loadAddresses[0].begin(), module.loadAddresses[0].end()));
debugEvent.type = ZET_DEBUG_EVENT_TYPE_MODULE_UNLOAD;
debugEvent.info.module.format = ZET_MODULE_DEBUG_INFO_FORMAT_ELF_DWARF;
debugEvent.info.module.load = loadAddress;
debugEvent.info.module.moduleBegin = reinterpret_cast<uint64_t>(metaDataEntry.data.get());
debugEvent.info.module.moduleEnd = reinterpret_cast<uint64_t>(metaDataEntry.data.get()) + metaDataEntry.metadata.len;
pushApiEvent(debugEvent, metaDataEntry.metadata.metadata_handle);
shouldAckEvent = false;
module.loadAddresses[0].clear();
module.moduleLoadEventAcked[0] = false;
}
}
}
}
if (shouldAckEvent && (vmBindData.vmBindUfence.base.flags & DRM_XE_EUDEBUG_EVENT_NEED_ACK)) {
drm_xe_eudebug_ack_event eventToAck = {};
eventToAck.type = vmBindData.vmBindUfence.base.type;
eventToAck.seqno = vmBindData.vmBindUfence.base.seqno;
eventToAck.flags = 0;
auto ret = ioctl(DRM_XE_EUDEBUG_IOCTL_ACK_EVENT, &eventToAck);
PRINT_DEBUGGER_INFO_LOG("DRM_XE_EUDEBUG_IOCTL_ACK_EVENT seqno = %llu ret = %d errno = %d\n", static_cast<uint64_t>(eventToAck.seqno), ret, ret != 0 ? errno : 0);
}
}
void DebugSessionLinuxXe::handleMetadataEvent(drm_xe_eudebug_event_metadata *metaData) {
bool destroy = metaData->base.flags & DRM_XE_EUDEBUG_EVENT_DESTROY;
bool create = metaData->base.flags & DRM_XE_EUDEBUG_EVENT_CREATE;

View File

@@ -77,6 +77,7 @@ struct DebugSessionLinuxXe : DebugSessionLinux {
int threadControlResumeAndStopped(const std::vector<EuThread::ThreadId> &threads, drm_xe_eudebug_eu_control &euControl, std::unique_ptr<uint8_t[]> &bitmaskOut, size_t &bitmaskSizeOut);
void handleAttentionEvent(drm_xe_eudebug_event_eu_attention *attention);
void handleMetadataEvent(drm_xe_eudebug_event_metadata *pMetaData);
bool handleMetadataOpEvent(drm_xe_eudebug_event_vm_bind_op_metadata *vmBindOpMetadata);
void updateContextAndLrcHandlesForThreadsWithAttention(EuThread::ThreadId threadId, AttentionEventFields &attention) override;
void startAsyncThread() override;
@@ -100,10 +101,6 @@ struct DebugSessionLinuxXe : DebugSessionLinux {
int openVmFd(uint64_t vmHandle, bool readOnly) override;
int flushVmCache(int vmfd) override;
void enqueueApiEvent(zet_debug_event_t &debugEvent) override {
UNRECOVERABLE_IF(true);
}
void attachTile() override {
UNRECOVERABLE_IF(true);
}
@@ -116,6 +113,21 @@ struct DebugSessionLinuxXe : DebugSessionLinux {
std::unique_ptr<char[]> data;
};
using VmBindOpSeqNo = uint64_t;
using VmBindSeqNo = uint64_t;
struct VmBindOpData {
uint64_t pendingNumExtensions = 0;
drm_xe_eudebug_event_vm_bind_op vmBindOp;
std::vector<drm_xe_eudebug_event_vm_bind_op_metadata> vmBindOpMetadataVec;
};
struct VmBindData {
uint64_t pendingNumBinds = 0;
drm_xe_eudebug_event_vm_bind vmBind;
drm_xe_eudebug_event_vm_bind_ufence vmBindUfence;
std::unordered_map<VmBindOpSeqNo, VmBindOpData> vmBindOpMap;
};
struct ClientConnectionXe : public ClientConnection {
drm_xe_eudebug_event_client client = {};
size_t getElfSize(uint64_t elfHandle) override { return 0; };
@@ -125,15 +137,18 @@ struct DebugSessionLinuxXe : DebugSessionLinux {
std::unordered_map<uint64_t, uint64_t> lrcHandleToVmHandle;
std::unordered_map<uint64_t, MetaData> metaDataMap;
std::unordered_map<uint64_t, Module> metaDataToModule;
std::unordered_map<VmBindSeqNo, VmBindData> vmBindMap;
std::unordered_map<VmBindOpSeqNo, VmBindSeqNo> vmBindIdentifierMap;
};
std::unordered_map<uint64_t, std::shared_ptr<ClientConnectionXe>> clientHandleToConnection;
void handleVmBind(VmBindData &vmBindData);
void handleVmBindWithoutUfence(VmBindData &vmBindData, VmBindOpData &vmBindOpData);
void extractMetaData(uint64_t client, const MetaData &metaData);
std::vector<std::unique_ptr<uint64_t[]>> pendingVmBindEvents;
bool checkAllEventsCollected();
MOCKABLE_VIRTUAL void handleEvent(drm_xe_eudebug_event *event);
void readInternalEventsAsync() override;
void pushApiEvent(zet_debug_event_t &debugEvent);
std::atomic<bool> detached{false};
uint64_t getVmHandleFromClientAndlrcHandle(uint64_t clientHandle, uint64_t lrcHandle) override;

View File

@@ -597,7 +597,7 @@ TEST_F(DebugApiLinuxTest, GivenEventRequiringAckWhenAcknowledgeEventCalledThenSu
auto isa = std::make_unique<DebugSessionLinuxi915::IsaAllocation>();
isa->bindInfo = {isaGpuVa, isaSize};
isa->vmHandle = 3;
isa->elfUuidHandle = DebugSessionLinuxi915::invalidHandle;
isa->elfHandle = DebugSessionLinuxi915::invalidHandle;
isa->moduleBegin = 0;
isa->moduleEnd = 0;
@@ -1508,7 +1508,7 @@ TEST_F(DebugApiLinuxTest, WhenCallingReadMemoryForISAThenMemoryIsRead) {
auto isa = std::make_unique<DebugSessionLinuxi915::IsaAllocation>();
isa->bindInfo = {isaGpuVa, isaSize};
isa->vmHandle = 3;
isa->elfUuidHandle = DebugSessionLinuxi915::invalidHandle;
isa->elfHandle = DebugSessionLinuxi915::invalidHandle;
isa->moduleBegin = 0;
isa->moduleEnd = 0;
@@ -1550,7 +1550,7 @@ TEST_F(DebugApiLinuxTest, GivenCanonizedAddressWhenGettingIsaVmHandleThenCorrect
auto isa = std::make_unique<DebugSessionLinuxi915::IsaAllocation>();
isa->bindInfo = {isaGpuVa, isaSize};
isa->vmHandle = 3;
isa->elfUuidHandle = DebugSessionLinuxi915::invalidHandle;
isa->elfHandle = DebugSessionLinuxi915::invalidHandle;
isa->moduleBegin = 0;
isa->moduleEnd = 0;
@@ -1747,7 +1747,7 @@ TEST_F(DebugApiLinuxTest, WhenCallingReadMemoryForISAForExpectedFailureCasesThen
auto isa = std::make_unique<DebugSessionLinuxi915::IsaAllocation>();
isa->bindInfo = {isaGpuVa, isaSize};
isa->vmHandle = 3;
isa->elfUuidHandle = DebugSessionLinuxi915::invalidHandle;
isa->elfHandle = DebugSessionLinuxi915::invalidHandle;
isa->moduleBegin = 0;
isa->moduleEnd = 0;
isaMap[isaGpuVa] = std::move(isa);
@@ -1897,7 +1897,7 @@ TEST_F(DebugApiLinuxTest, WhenCallingWriteMemoryForISAThenMemoryIsWritten) {
auto isa = std::make_unique<DebugSessionLinuxi915::IsaAllocation>();
isa->bindInfo = {isaGpuVa, isaSize};
isa->vmHandle = 3;
isa->elfUuidHandle = DebugSessionLinuxi915::invalidHandle;
isa->elfHandle = DebugSessionLinuxi915::invalidHandle;
isa->moduleBegin = 0;
isa->moduleEnd = 0;
@@ -2050,7 +2050,7 @@ TEST_F(DebugApiLinuxTest, WhenCallingWriteMemoryForExpectedFailureCasesThenError
auto isa = std::make_unique<DebugSessionLinuxi915::IsaAllocation>();
isa->bindInfo = {isaGpuVa, isaSize};
isa->vmHandle = 3;
isa->elfUuidHandle = DebugSessionLinuxi915::invalidHandle;
isa->elfHandle = DebugSessionLinuxi915::invalidHandle;
isa->moduleBegin = 0;
isa->moduleEnd = 0;
isaMap[isaGpuVa] = std::move(isa);
@@ -4133,7 +4133,7 @@ TEST_F(DebugApiLinuxVmBindTest, GivenVmBindEventWithAckNeededForIsaWhenHandlingE
auto isaAllocation = isaMap[isaGpuVa].get();
EXPECT_EQ(isaGpuVa, isaAllocation->bindInfo.gpuVa);
EXPECT_EQ(isaSize, isaAllocation->bindInfo.size);
EXPECT_EQ(elfUUID, isaAllocation->elfUuidHandle);
EXPECT_EQ(elfUUID, isaAllocation->elfHandle);
EXPECT_EQ(3u, isaAllocation->vmHandle);
EXPECT_TRUE(isaAllocation->tileInstanced);
@@ -4177,7 +4177,7 @@ TEST_F(DebugApiLinuxVmBindTest, GivenCookieWhenHandlingVmBindForIsaThenIsaAlloca
auto isaAllocation = isaMap[isaGpuVa].get();
EXPECT_EQ(isaGpuVa, isaAllocation->bindInfo.gpuVa);
EXPECT_EQ(isaSize, isaAllocation->bindInfo.size);
EXPECT_EQ(elfUUID, isaAllocation->elfUuidHandle);
EXPECT_EQ(elfUUID, isaAllocation->elfHandle);
EXPECT_EQ(3u, isaAllocation->vmHandle);
EXPECT_TRUE(isaAllocation->tileInstanced);
}
@@ -4215,7 +4215,7 @@ TEST_F(DebugApiLinuxVmBindTest, GivenNoCookieWhenHandlingVmBindForIsaThenIsaAllo
auto isaAllocation = isaMap[isaGpuVa].get();
EXPECT_EQ(isaGpuVa, isaAllocation->bindInfo.gpuVa);
EXPECT_EQ(isaSize, isaAllocation->bindInfo.size);
EXPECT_EQ(elfUUID, isaAllocation->elfUuidHandle);
EXPECT_EQ(elfUUID, isaAllocation->elfHandle);
EXPECT_EQ(3u, isaAllocation->vmHandle);
EXPECT_FALSE(isaAllocation->tileInstanced);
}
@@ -4405,7 +4405,7 @@ TEST_F(DebugApiLinuxVmBindTest, GivenIsaBoundMultipleTimesWhenHandlingVmBindDest
auto isa = std::make_unique<DebugSessionLinuxi915::IsaAllocation>();
isa->bindInfo = {isaGpuVa, isaSize};
isa->vmHandle = 3;
isa->elfUuidHandle = DebugSessionLinuxi915::invalidHandle;
isa->elfHandle = DebugSessionLinuxi915::invalidHandle;
isa->moduleBegin = 0;
isa->moduleEnd = 0;
isa->vmBindCounter = 5;

View File

@@ -1094,6 +1094,458 @@ TEST_F(DebugApiLinuxTestXe, GivenMetadataEventWhenHandlingEventThenGpuAddressIsS
EXPECT_EQ(contextSaveAddress, session->clientHandleToConnection[MockDebugSessionLinuxXe::mockClientHandle]->contextStateSaveAreaGpuVa);
}
TEST_F(DebugApiLinuxTestXe, GivenVmBindEventWhenHandlingEventThenVmBindMapIsCorrectlyUpdated) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
ASSERT_NE(nullptr, session);
session->clientHandle = DebugSessionLinuxXe::invalidClientHandle;
auto handler = new MockIoctlHandlerXe;
session->ioctlHandler.reset(handler);
session->clientHandleToConnection.clear();
drm_xe_eudebug_event_client client1;
client1.base.type = DRM_XE_EUDEBUG_EVENT_OPEN;
client1.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
client1.client_handle = 0x123456789;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&client1));
drm_xe_eudebug_event_vm_bind vmBind1{};
vmBind1.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND;
vmBind1.base.flags = DRM_XE_EUDEBUG_EVENT_STATE_CHANGE;
vmBind1.base.len = sizeof(drm_xe_eudebug_event_vm_bind);
vmBind1.base.seqno = 1;
vmBind1.client_handle = client1.client_handle;
vmBind1.flags = DRM_XE_EUDEBUG_EVENT_VM_BIND_FLAG_UFENCE;
vmBind1.num_binds = 2;
EXPECT_EQ(session->clientHandleToConnection[client1.client_handle]->vmBindMap.size(), 0u);
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBind1.base));
vmBind1.base.seqno = 2;
vmBind1.client_handle = client1.client_handle;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBind1.base));
EXPECT_EQ(session->clientHandleToConnection[client1.client_handle]->vmBindMap.size(), 2u);
}
TEST_F(DebugApiLinuxTestXe, GivenVmBindOpEventWhenHandlingEventThenVmBindMapIsCorrectlyUpdated) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
ASSERT_NE(nullptr, session);
auto handler = new MockIoctlHandlerXe;
session->ioctlHandler.reset(handler);
session->clientHandleToConnection.clear();
drm_xe_eudebug_event_client client1;
client1.base.type = DRM_XE_EUDEBUG_EVENT_OPEN;
client1.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
client1.client_handle = MockDebugSessionLinuxXe::mockClientHandle;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&client1));
drm_xe_eudebug_event_vm_bind vmBind{};
vmBind.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND;
vmBind.base.flags = DRM_XE_EUDEBUG_EVENT_STATE_CHANGE;
vmBind.base.len = sizeof(drm_xe_eudebug_event_vm_bind);
vmBind.base.seqno = 1;
vmBind.client_handle = client1.client_handle;
vmBind.flags = DRM_XE_EUDEBUG_EVENT_VM_BIND_FLAG_UFENCE;
vmBind.num_binds = 2;
auto &vmBindMap = session->clientHandleToConnection[client1.client_handle]->vmBindMap;
EXPECT_EQ(vmBindMap.size(), 0u);
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBind.base));
EXPECT_EQ(vmBindMap.size(), 1u);
EXPECT_EQ(vmBindMap[vmBind.base.seqno].pendingNumBinds, 2ull);
drm_xe_eudebug_event_vm_bind_op vmBindOp{};
vmBindOp.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND_OP;
vmBindOp.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
vmBindOp.base.len = sizeof(drm_xe_eudebug_event_vm_bind_op);
vmBindOp.base.seqno = 2;
vmBindOp.num_extensions = 2;
vmBindOp.addr = 0xffff1234;
vmBindOp.range = 65536;
vmBindOp.vm_bind_ref_seqno = vmBind.base.seqno;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBindOp.base));
EXPECT_EQ(vmBindMap[vmBind.base.seqno].pendingNumBinds, 1ull);
EXPECT_EQ(session->clientHandleToConnection[client1.client_handle]->vmBindIdentifierMap[vmBindOp.base.seqno], vmBindOp.vm_bind_ref_seqno);
auto &vmBindOpData = vmBindMap[vmBindOp.vm_bind_ref_seqno].vmBindOpMap[vmBindOp.base.seqno];
EXPECT_EQ(vmBindOpData.pendingNumExtensions, vmBindOp.num_extensions);
EXPECT_TRUE(0 == std::memcmp(&vmBindOp, &vmBindOpData.vmBindOp, sizeof(drm_xe_eudebug_event_vm_bind_op)));
}
class DebugApiLinuxTestXeMetadataOpEventTest : public DebugApiLinuxTestXe,
public ::testing::WithParamInterface<uint64_t> {
public:
uint64_t metadataType;
DebugApiLinuxTestXeMetadataOpEventTest() {
metadataType = GetParam();
}
~DebugApiLinuxTestXeMetadataOpEventTest() override {}
};
TEST_P(DebugApiLinuxTestXeMetadataOpEventTest, GivenVmBindOpMetadataEventForMetadataAreaWhenHandlingEventThenMapIsCorrectlyUpdated) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
ASSERT_NE(nullptr, session);
auto handler = new MockIoctlHandlerXe;
session->ioctlHandler.reset(handler);
session->clientHandleToConnection.clear();
drm_xe_eudebug_event_client client1;
client1.base.type = DRM_XE_EUDEBUG_EVENT_OPEN;
client1.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
client1.client_handle = MockDebugSessionLinuxXe::mockClientHandle;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&client1));
auto &connection = session->clientHandleToConnection[MockDebugSessionLinuxXe::mockClientHandle];
drm_xe_eudebug_event_metadata metadata{};
metadata.base.type = DRM_XE_EUDEBUG_EVENT_METADATA;
metadata.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
metadata.base.len = sizeof(drm_xe_eudebug_event_metadata);
metadata.client_handle = MockDebugSessionLinuxXe::mockClientHandle;
metadata.metadata_handle = 10;
metadata.type = metadataType;
metadata.len = sizeof(metadata);
connection->metaDataMap[10].metadata = metadata;
drm_xe_eudebug_event_vm_bind vmBind{};
vmBind.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND;
vmBind.base.flags = DRM_XE_EUDEBUG_EVENT_STATE_CHANGE;
vmBind.base.len = sizeof(drm_xe_eudebug_event_vm_bind);
vmBind.base.seqno = 1;
vmBind.client_handle = client1.client_handle;
vmBind.vm_handle = 0x1234;
vmBind.flags = DRM_XE_EUDEBUG_EVENT_VM_BIND_FLAG_UFENCE;
vmBind.num_binds = 1;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBind.base));
auto &vmBindMap = session->clientHandleToConnection[client1.client_handle]->vmBindMap;
drm_xe_eudebug_event_vm_bind_op vmBindOp{};
vmBindOp.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND_OP;
vmBindOp.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
vmBindOp.base.len = sizeof(drm_xe_eudebug_event_vm_bind_op);
vmBindOp.base.seqno = 2;
vmBindOp.num_extensions = 1;
vmBindOp.addr = 0xffff1234;
vmBindOp.range = 1000;
vmBindOp.vm_bind_ref_seqno = vmBind.base.seqno;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBindOp.base));
auto &vmBindOpData = vmBindMap[vmBindOp.vm_bind_ref_seqno].vmBindOpMap[vmBindOp.base.seqno];
drm_xe_eudebug_event_vm_bind_op_metadata vmBindOpMetadata{};
vmBindOpMetadata.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND_OP_METADATA;
vmBindOpMetadata.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
vmBindOpMetadata.base.len = sizeof(drm_xe_eudebug_event_vm_bind_op_metadata);
vmBindOpMetadata.base.seqno = 3;
vmBindOpMetadata.vm_bind_op_ref_seqno = vmBindOp.base.seqno;
vmBindOpMetadata.metadata_handle = 10;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBindOpMetadata.base));
EXPECT_EQ(vmBindOpData.pendingNumExtensions, 0ull);
EXPECT_EQ(vmBindOpData.vmBindOpMetadataVec.size(), 1ull);
drm_xe_eudebug_event_vm_bind_ufence vmBindUfence{};
vmBindUfence.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE;
vmBindUfence.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE | DRM_XE_EUDEBUG_EVENT_NEED_ACK;
vmBindUfence.base.len = sizeof(drm_xe_eudebug_event_vm_bind_ufence);
vmBindUfence.base.seqno = 4;
vmBindUfence.vm_bind_ref_seqno = vmBind.base.seqno;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBindUfence.base));
if (metadataType == WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_SBA_AREA) {
EXPECT_EQ(connection->vmToStateBaseAreaBindInfo[0x1234].gpuVa, vmBindOp.addr);
EXPECT_EQ(connection->vmToStateBaseAreaBindInfo[0x1234].size, vmBindOp.range);
}
if (metadataType == WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_MODULE_AREA) {
EXPECT_EQ(connection->vmToModuleDebugAreaBindInfo[0x1234].gpuVa, vmBindOp.addr);
EXPECT_EQ(connection->vmToModuleDebugAreaBindInfo[0x1234].size, vmBindOp.range);
}
if (metadataType == WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_SIP_AREA) {
EXPECT_EQ(connection->vmToContextStateSaveAreaBindInfo[0x1234].gpuVa, vmBindOp.addr);
EXPECT_EQ(connection->vmToContextStateSaveAreaBindInfo[0x1234].size, vmBindOp.range);
}
if (metadataType == DRM_XE_DEBUG_METADATA_ELF_BINARY) {
EXPECT_EQ(connection->isaMap[0][vmBindOp.addr]->bindInfo.gpuVa, vmBindOp.addr);
EXPECT_EQ(connection->isaMap[0][vmBindOp.addr]->bindInfo.size, vmBindOp.range);
EXPECT_FALSE(connection->isaMap[0][vmBindOp.addr]->tileInstanced);
EXPECT_FALSE(connection->isaMap[0][vmBindOp.addr]->perKernelModule);
}
}
static uint64_t metadataTypes[] =
{
WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_MODULE_AREA,
WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_SBA_AREA,
WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_SIP_AREA,
DRM_XE_DEBUG_METADATA_ELF_BINARY};
INSTANTIATE_TEST_CASE_P(
MetadataOpEventUfenceTest,
DebugApiLinuxTestXeMetadataOpEventTest,
testing::ValuesIn(metadataTypes));
TEST_F(DebugApiLinuxTestXe, GivenVmBindOpMetadataCreateEventAndUfenceForProgramModuleWhenHandlingEventThenEventIsAcked) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
ASSERT_NE(nullptr, session);
auto handler = new MockIoctlHandlerXe;
session->ioctlHandler.reset(handler);
session->clientHandleToConnection.clear();
drm_xe_eudebug_event_client client1;
client1.base.type = DRM_XE_EUDEBUG_EVENT_OPEN;
client1.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
client1.client_handle = MockDebugSessionLinuxXe::mockClientHandle;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&client1));
auto &connection = session->clientHandleToConnection[MockDebugSessionLinuxXe::mockClientHandle];
drm_xe_eudebug_event_metadata metadata{};
metadata.base.type = DRM_XE_EUDEBUG_EVENT_METADATA;
metadata.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
metadata.base.len = sizeof(drm_xe_eudebug_event_metadata);
metadata.client_handle = MockDebugSessionLinuxXe::mockClientHandle;
metadata.metadata_handle = 10;
metadata.type = DRM_XE_DEBUG_METADATA_PROGRAM_MODULE;
metadata.len = sizeof(metadata);
connection->metaDataMap[10].metadata = metadata;
connection->metaDataToModule[10].segmentCount = 1;
drm_xe_eudebug_event_vm_bind vmBind{};
vmBind.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND;
vmBind.base.flags = DRM_XE_EUDEBUG_EVENT_STATE_CHANGE;
vmBind.base.len = sizeof(drm_xe_eudebug_event_vm_bind);
vmBind.base.seqno = 1;
vmBind.client_handle = client1.client_handle;
vmBind.vm_handle = 0x1234;
vmBind.flags = DRM_XE_EUDEBUG_EVENT_VM_BIND_FLAG_UFENCE;
vmBind.num_binds = 1;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBind.base));
auto &vmBindMap = session->clientHandleToConnection[client1.client_handle]->vmBindMap;
drm_xe_eudebug_event_vm_bind_op vmBindOp{};
vmBindOp.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND_OP;
vmBindOp.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
vmBindOp.base.len = sizeof(drm_xe_eudebug_event_vm_bind_op);
vmBindOp.base.seqno = 2;
vmBindOp.num_extensions = 1;
vmBindOp.addr = 0xffff1234;
vmBindOp.range = 1000;
vmBindOp.vm_bind_ref_seqno = vmBind.base.seqno;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBindOp.base));
auto &vmBindOpData = vmBindMap[vmBindOp.vm_bind_ref_seqno].vmBindOpMap[vmBindOp.base.seqno];
drm_xe_eudebug_event_vm_bind_op_metadata vmBindOpMetadata{};
vmBindOpMetadata.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND_OP_METADATA;
vmBindOpMetadata.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
vmBindOpMetadata.base.len = sizeof(drm_xe_eudebug_event_vm_bind_op_metadata);
vmBindOpMetadata.base.seqno = 3;
vmBindOpMetadata.vm_bind_op_ref_seqno = vmBindOp.base.seqno;
vmBindOpMetadata.metadata_handle = 10;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBindOpMetadata.base));
EXPECT_EQ(vmBindOpData.pendingNumExtensions, 0ull);
EXPECT_EQ(vmBindOpData.vmBindOpMetadataVec.size(), 1ull);
drm_xe_eudebug_event_vm_bind_ufence vmBindUfence{};
vmBindUfence.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE;
vmBindUfence.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE | DRM_XE_EUDEBUG_EVENT_NEED_ACK;
vmBindUfence.base.len = sizeof(drm_xe_eudebug_event_vm_bind_ufence);
vmBindUfence.base.seqno = 4;
vmBindUfence.vm_bind_ref_seqno = vmBind.base.seqno;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBindUfence.base));
EXPECT_EQ(connection->metaDataToModule[10].ackEvents->size(), 1ull);
EXPECT_EQ(connection->metaDataToModule[10].ackEvents[0][0].seqno, vmBindUfence.base.seqno);
EXPECT_EQ(connection->metaDataToModule[10].ackEvents[0][0].type, vmBindUfence.base.type);
}
TEST_F(DebugApiLinuxTestXe, GivenModuleDestroyEventAndUfenceForProgramModuleWhenHandlingEventThenEventIsGenerated) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
ASSERT_NE(nullptr, session);
auto handler = new MockIoctlHandlerXe;
session->ioctlHandler.reset(handler);
session->clientHandleToConnection.clear();
drm_xe_eudebug_event_client client1;
client1.base.type = DRM_XE_EUDEBUG_EVENT_OPEN;
client1.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
client1.client_handle = MockDebugSessionLinuxXe::mockClientHandle;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&client1));
auto &connection = session->clientHandleToConnection[MockDebugSessionLinuxXe::mockClientHandle];
drm_xe_eudebug_event_metadata metadata{};
metadata.base.type = DRM_XE_EUDEBUG_EVENT_METADATA;
metadata.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
metadata.base.len = sizeof(drm_xe_eudebug_event_metadata);
metadata.client_handle = MockDebugSessionLinuxXe::mockClientHandle;
metadata.metadata_handle = 10;
metadata.type = DRM_XE_DEBUG_METADATA_PROGRAM_MODULE;
metadata.len = sizeof(metadata);
connection->metaDataMap[10].metadata = metadata;
connection->metaDataToModule[10].segmentCount = 1;
connection->metaDataToModule[10].segmentVmBindCounter[0] = 1;
connection->metaDataToModule[10].loadAddresses[0].insert(0xffff1234);
drm_xe_eudebug_event_vm_bind vmBind{};
vmBind.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND;
vmBind.base.flags = DRM_XE_EUDEBUG_EVENT_STATE_CHANGE;
vmBind.base.len = sizeof(drm_xe_eudebug_event_vm_bind);
vmBind.base.seqno = 1;
vmBind.client_handle = client1.client_handle;
vmBind.vm_handle = 0x1234;
vmBind.flags = DRM_XE_EUDEBUG_EVENT_VM_BIND_FLAG_UFENCE;
vmBind.num_binds = 1;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBind.base));
auto &vmBindMap = session->clientHandleToConnection[client1.client_handle]->vmBindMap;
drm_xe_eudebug_event_vm_bind_op vmBindOp{};
vmBindOp.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND_OP;
vmBindOp.base.flags = DRM_XE_EUDEBUG_EVENT_DESTROY;
vmBindOp.base.len = sizeof(drm_xe_eudebug_event_vm_bind_op);
vmBindOp.base.seqno = 2;
vmBindOp.num_extensions = 1;
vmBindOp.addr = 0xffff1234;
vmBindOp.range = 1000;
vmBindOp.vm_bind_ref_seqno = vmBind.base.seqno;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBindOp.base));
auto &vmBindOpData = vmBindMap[vmBindOp.vm_bind_ref_seqno].vmBindOpMap[vmBindOp.base.seqno];
drm_xe_eudebug_event_vm_bind_op_metadata vmBindOpMetadata{};
vmBindOpMetadata.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND_OP_METADATA;
vmBindOpMetadata.base.flags = DRM_XE_EUDEBUG_EVENT_DESTROY;
vmBindOpMetadata.base.len = sizeof(drm_xe_eudebug_event_vm_bind_op_metadata);
vmBindOpMetadata.base.seqno = 3;
vmBindOpMetadata.vm_bind_op_ref_seqno = vmBindOp.base.seqno;
vmBindOpMetadata.metadata_handle = 10;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBindOpMetadata.base));
EXPECT_EQ(vmBindOpData.pendingNumExtensions, 0ull);
EXPECT_EQ(vmBindOpData.vmBindOpMetadataVec.size(), 1ull);
drm_xe_eudebug_event_vm_bind_ufence vmBindUfence{};
vmBindUfence.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND_UFENCE;
vmBindUfence.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE | DRM_XE_EUDEBUG_EVENT_NEED_ACK;
vmBindUfence.base.len = sizeof(drm_xe_eudebug_event_vm_bind_ufence);
vmBindUfence.base.seqno = 4;
vmBindUfence.vm_bind_ref_seqno = vmBind.base.seqno;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBindUfence.base));
auto event = session->apiEvents.front();
EXPECT_EQ(ZET_DEBUG_EVENT_TYPE_MODULE_UNLOAD, event.type);
}
TEST_F(DebugApiLinuxTestXe, GivenVmBindOpMetadataEventAndUfenceNotProvidedForProgramModuleWhenHandlingEventThenEventIsNotAckedButHandled) {
zet_debug_config_t config = {};
config.pid = 0x1234;
auto session = std::make_unique<MockDebugSessionLinuxXe>(config, device, 10);
ASSERT_NE(nullptr, session);
auto handler = new MockIoctlHandlerXe;
session->ioctlHandler.reset(handler);
session->clientHandleToConnection.clear();
drm_xe_eudebug_event_client client1;
client1.base.type = DRM_XE_EUDEBUG_EVENT_OPEN;
client1.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
client1.client_handle = MockDebugSessionLinuxXe::mockClientHandle;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&client1));
auto &connection = session->clientHandleToConnection[MockDebugSessionLinuxXe::mockClientHandle];
drm_xe_eudebug_event_metadata metadata{};
metadata.base.type = DRM_XE_EUDEBUG_EVENT_METADATA;
metadata.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
metadata.base.len = sizeof(drm_xe_eudebug_event_metadata);
metadata.client_handle = MockDebugSessionLinuxXe::mockClientHandle;
metadata.metadata_handle = 10;
metadata.type = DRM_XE_DEBUG_METADATA_PROGRAM_MODULE;
metadata.len = sizeof(metadata);
connection->metaDataMap[10].metadata = metadata;
metadata.metadata_handle = 11;
metadata.type = WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_SBA_AREA;
connection->metaDataMap[11].metadata = metadata;
metadata.metadata_handle = 12;
metadata.type = WORK_IN_PROGRESS_DRM_XE_DEBUG_METADATA_SIP_AREA;
connection->metaDataMap[12].metadata = metadata;
connection->metaDataToModule[10].segmentCount = 1;
drm_xe_eudebug_event_vm_bind vmBind{};
vmBind.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND;
vmBind.base.flags = DRM_XE_EUDEBUG_EVENT_STATE_CHANGE;
vmBind.base.len = sizeof(drm_xe_eudebug_event_vm_bind);
vmBind.base.seqno = 1;
vmBind.client_handle = client1.client_handle;
vmBind.vm_handle = 0x1234;
vmBind.num_binds = 2;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBind.base));
auto &vmBindMap = session->clientHandleToConnection[client1.client_handle]->vmBindMap;
drm_xe_eudebug_event_vm_bind_op vmBindOp{};
// first vm_bind_op
vmBindOp.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND_OP;
vmBindOp.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
vmBindOp.base.len = sizeof(drm_xe_eudebug_event_vm_bind_op);
vmBindOp.base.seqno = 2;
vmBindOp.num_extensions = 2;
vmBindOp.addr = 0xffff1234;
vmBindOp.range = 1000;
vmBindOp.vm_bind_ref_seqno = vmBind.base.seqno;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBindOp.base));
auto &vmBindOpData = vmBindMap[vmBindOp.vm_bind_ref_seqno].vmBindOpMap[vmBindOp.base.seqno];
drm_xe_eudebug_event_vm_bind_op_metadata vmBindOpMetadata{};
vmBindOpMetadata.base.type = DRM_XE_EUDEBUG_EVENT_VM_BIND_OP_METADATA;
vmBindOpMetadata.base.flags = DRM_XE_EUDEBUG_EVENT_CREATE;
vmBindOpMetadata.base.len = sizeof(drm_xe_eudebug_event_vm_bind_op_metadata);
vmBindOpMetadata.base.seqno = 3;
vmBindOpMetadata.vm_bind_op_ref_seqno = vmBindOp.base.seqno;
vmBindOpMetadata.metadata_handle = 10;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBindOpMetadata.base));
vmBindOpMetadata.base.seqno = 4;
vmBindOpMetadata.metadata_handle = 11;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBindOpMetadata.base));
// second vm_bind_op
vmBindOp.base.seqno = 5;
vmBindOp.num_extensions = 1;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBindOp.base));
vmBindOpMetadata.vm_bind_op_ref_seqno = 5;
vmBindOpMetadata.base.seqno = 6;
vmBindOpMetadata.metadata_handle = 12;
session->handleEvent(reinterpret_cast<drm_xe_eudebug_event *>(&vmBindOpMetadata.base));
EXPECT_EQ(vmBindOpData.pendingNumExtensions, 0ull);
EXPECT_EQ(vmBindOpData.vmBindOpMetadataVec.size(), 2ull);
EXPECT_EQ(vmBindMap[vmBindOp.vm_bind_ref_seqno].vmBindOpMap[5].pendingNumExtensions, 0ull);
EXPECT_EQ(vmBindMap[vmBindOp.vm_bind_ref_seqno].vmBindOpMap[5].vmBindOpMetadataVec.size(), 1ull);
EXPECT_EQ(connection->metaDataToModule[10].ackEvents->size(), 0ull);
}
TEST_F(DebugApiLinuxTestXe, WhenCallingReadAndWriteGpuMemoryThenFsyncIsCalledTwice) {
auto session = std::make_unique<MockDebugSessionLinuxXe>(zet_debug_config_t{0x1234}, device, 10);
ASSERT_NE(nullptr, session);

View File

@@ -24,7 +24,7 @@ extern "C" {
#define DRM_XE_EUDEBUG_IOCTL_EU_CONTROL _IOWR('j', 0x2, struct drm_xe_eudebug_eu_control)
#define DRM_XE_EUDEBUG_IOCTL_VM_OPEN _IOW('j', 0x1, struct drm_xe_eudebug_vm_open)
#define DRM_XE_EUDEBUG_IOCTL_READ_METADATA _IOWR('j', 0x3, struct drm_xe_eudebug_read_metadata)
#define DRM_XE_EUDEBUG_IOCTL_ACK_EVENT _IOW('j', 0x4, struct drm_xe_eudebug_event_ack)
#define DRM_XE_EUDEBUG_IOCTL_ACK_EVENT _IOW('j', 0x4, struct drm_xe_eudebug_ack_event)
/* XXX: Document events to match their internal counterparts when moved to xe_drm.h */
struct drm_xe_eudebug_event {
@@ -43,7 +43,9 @@ struct drm_xe_eudebug_event {
#define DRM_XE_EUDEBUG_EVENT_METADATA 9
#define DRM_XE_EUDEBUG_EVENT_VM_BIND_OP_METADATA 10
#define DRM_XE_EUDEBUG_EVENT_VM_SET_METADATA 11
#define DRM_XE_EUDEBUG_EVENT_MAX_EVENT DRM_XE_EUDEBUG_EVENT_VM_SET_METADATA
#define DRM_XE_EUDEBUG_EVENT_PAGEFAULT 12
#define DRM_XE_EUDEBUG_EVENT_SYNC_HOST 13
#define DRM_XE_EUDEBUG_EVENT_MAX_EVENT DRM_XE_EUDEBUG_EVENT_SYNC_HOST
__u16 flags;
#define DRM_XE_EUDEBUG_EVENT_CREATE (1 << 0)
@@ -74,13 +76,14 @@ struct drm_xe_eudebug_event_exec_queue {
__u64 client_handle;
__u64 vm_handle;
__u64 exec_queue_handle;
__u16 engine_class;
__u16 width;
__u32 engine_class;
__u32 width;
__u64 lrc_handle[0];
} __attribute__((packed));
struct drm_xe_eudebug_event_eu_attention {
struct drm_xe_eudebug_event base;
__u64 client_handle;
__u64 exec_queue_handle;
__u64 lrc_handle;
@@ -94,7 +97,10 @@ struct drm_xe_eudebug_event_vm_bind {
__u64 client_handle;
__u64 vm_handle;
__u64 num_binds;
__u32 flags;
#define DRM_XE_EUDEBUG_EVENT_VM_BIND_FLAG_UFENCE (1 << 0)
__u32 num_binds;
} __attribute__((packed));
struct drm_xe_eudebug_event_vm_bind_op {
@@ -121,13 +127,13 @@ struct drm_xe_eudebug_event_metadata {
__u64 len;
} __attribute__((packed));
struct drm_xe_eudebug_vm_bind_op_metadata {
struct drm_xe_eudebug_event_vm_bind_op_metadata {
struct drm_xe_eudebug_event base;
__u64 vm_bind_op_ref_seqno; /* *_event_vm_bind_op.base.seqno */
__u64 metadata_handle;
__u64 metadata_cookie;
};
} __attribute__((packed));
struct drm_xe_eudebug_event_vm_set_metadata {
struct drm_xe_eudebug_event base;
@@ -144,6 +150,27 @@ struct drm_xe_eudebug_event_vm_set_metadata {
__u64 len;
} __attribute__((packed));
struct drm_xe_eudebug_event_pagefault {
struct drm_xe_eudebug_event base;
__u64 client_handle;
__u64 exec_queue_handle;
__u64 lrc_handle;
__u64 pagefault_address;
__u32 fault_flags;
__u32 bitmask_size;
__u8 bitmask[0];
} __attribute__((packed));
struct drm_xe_eudebug_event_sync_host {
struct drm_xe_eudebug_event base;
__u64 client_handle;
__u64 exec_queue_handle;
__u64 lrc_handle;
} __attribute__((packed));
/*
* Debugger ABI (ioctl and events) Version History:
* 0 - No debugger available
@@ -163,10 +190,13 @@ struct drm_xe_eudebug_connect {
struct drm_xe_eudebug_eu_control {
__u64 client_handle;
__u32 cmd;
#define DRM_XE_EUDEBUG_EU_CONTROL_CMD_INTERRUPT_ALL 0
#define DRM_XE_EUDEBUG_EU_CONTROL_CMD_STOPPED 1
#define DRM_XE_EUDEBUG_EU_CONTROL_CMD_RESUME 2
#define DRM_XE_EUDEBUG_EU_CONTROL_CMD_UNLOCK 3
__u32 cmd;
__u32 flags;
__u64 seqno;
@@ -174,7 +204,7 @@ struct drm_xe_eudebug_eu_control {
__u64 lrc_handle;
__u32 bitmask_size;
__u64 bitmask_ptr;
} __attribute__((packed));
};
struct drm_xe_eudebug_vm_open {
/** @extensions: Pointer to the first extension struct, if any */
@@ -202,7 +232,7 @@ struct drm_xe_eudebug_read_metadata {
__u64 size;
};
struct drm_xe_eudebug_event_ack {
struct drm_xe_eudebug_ack_event {
__u32 type;
__u32 flags; /* MBZ */
__u64 seqno;
@@ -212,4 +242,4 @@ struct drm_xe_eudebug_event_ack {
}
#endif
#endif /* _UAPI_XE_DRM_TMP_H_ */
#endif /* _UAPI_XE_DRM_TMP_H_ */