fix: Modify VM_UNBIND to support EU debugger for shared system USM

Resolves: NEO-16798

Signed-off-by: John Falkowski <john.falkowski@intel.com>
This commit is contained in:
John Falkowski
2025-12-10 21:45:41 +00:00
committed by Compute-Runtime-Automation
parent c08c3f19b1
commit 8b0a42bff4
2 changed files with 198 additions and 16 deletions

View File

@@ -106,6 +106,14 @@ std::string IoctlHelperXe::xeGetBindFlagNames(int bindFlags) {
bindFlags &= ~DRM_XE_VM_BIND_FLAG_DUMPABLE;
flags += "DUMPABLE ";
}
if (bindFlags & DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR) {
bindFlags &= ~DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR;
flags += "CPU_ADDR_MIRROR ";
}
if (bindFlags & DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET) {
bindFlags &= ~DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET;
flags += "MADVISE_AUTORESET ";
}
if (bindFlags != 0) {
flags += "Unknown flag ";
@@ -1585,6 +1593,7 @@ int IoctlHelperXe::xeVmBind(const VmBindParams &vmBindParams, bool isBind) {
}
drm_xe_vm_bind bind = {};
drm_xe_vm_bind_op bindOps[2] = {};
bind.vm_id = vmBindParams.vmId;
bind.num_binds = 1;
@@ -1627,10 +1636,15 @@ int IoctlHelperXe::xeVmBind(const VmBindParams &vmBindParams, bool isBind) {
bind.bind.obj_offset = userptr;
}
} else {
if (vmBindParams.sharedSystemUsmEnabled) {
if ((vmBindParams.sharedSystemUsmEnabled) && ((bind.bind.addr + bind.bind.range) <= drm.getSharedSystemAllocAddressRange())) {
// Use of MAP on unbind required for restoring the address space to the system allocator
bind.bind.op = DRM_XE_VM_BIND_OP_MAP;
bind.bind.flags |= DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR;
memcpy(&bindOps[0], &bind.bind, sizeof(drm_xe_vm_bind_op));
memcpy(&bindOps[1], &bind.bind, sizeof(drm_xe_vm_bind_op));
bindOps[0].op = DRM_XE_VM_BIND_OP_UNMAP;
bindOps[1].op = DRM_XE_VM_BIND_OP_MAP;
bindOps[1].flags |= DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR;
bind.num_binds = 2;
bind.vector_of_binds = (uintptr_t)bindOps;
} else {
bind.bind.op = DRM_XE_VM_BIND_OP_UNMAP;
if (userptr) {
@@ -1642,19 +1656,41 @@ int IoctlHelperXe::xeVmBind(const VmBindParams &vmBindParams, bool isBind) {
ret = IoctlHelper::ioctl(DrmIoctl::gemVmBind, &bind);
XELOG(" vm=%d obj=0x%x off=0x%llx range=0x%llx addr=0x%llx operation=%d(%s) flags=%d(%s) nsy=%d pat=%hu ret=%d\n",
bind.vm_id,
bind.bind.obj,
bind.bind.obj_offset,
bind.bind.range,
bind.bind.addr,
bind.bind.op,
xeGetBindOperationName(bind.bind.op),
bind.bind.flags,
xeGetBindFlagNames(bind.bind.flags).c_str(),
bind.num_syncs,
bind.bind.pat_index,
ret);
if (bind.num_binds == 1) {
XELOG(" vm=%d obj=0x%x off=0x%llx range=0x%llx addr=0x%llx operation=%d(%s) flags=%d(%s) nsy=%d num_bind=%d pat=%hu ret=%d\n",
bind.vm_id,
bind.bind.obj,
bind.bind.obj_offset,
bind.bind.range,
bind.bind.addr,
bind.bind.op,
xeGetBindOperationName(bind.bind.op),
bind.bind.flags,
xeGetBindFlagNames(bind.bind.flags).c_str(),
bind.num_syncs,
bind.num_binds,
bind.bind.pat_index,
ret);
} else if (bind.num_binds == 2) {
XELOG(" vm=%d obj=0x%x off=0x%llx range=0x%llx addr=0x%llx operation[0]=%d(%s) flags[0]=%d(%s) operation[1]=%d(%s) flags[1]=%d(%s) nsy=%d num_bind=%d pat=%hu ret=%d\n",
bind.vm_id,
bind.bind.obj,
bind.bind.obj_offset,
bind.bind.range,
bind.bind.addr,
bindOps[0].op,
xeGetBindOperationName(bindOps[0].op),
bindOps[0].flags,
xeGetBindFlagNames(bindOps[0].flags).c_str(),
bindOps[1].op,
xeGetBindOperationName(bindOps[1].op),
bindOps[1].flags,
xeGetBindFlagNames(bindOps[1].flags).c_str(),
bind.num_syncs,
bind.num_binds,
bind.bind.pat_index,
ret);
}
if (ret != 0) {
XELOG("error: %s\n", operation);

View File

@@ -2257,6 +2257,152 @@ TEST_F(IoctlHelperXeTest, whenCallingVmUnbindThenPatIndexIsSetToDefault) {
EXPECT_EQ(drm->vmBindInputs[0].bind.pat_index, defaultPatIndex);
}
TEST_F(IoctlHelperXeTest, whenCallingVmUnbindAndSharedSystemUsmDisabledThenOneBindOps) {
DebugManagerStateRestore restorer;
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
auto drm = DrmMockXe::create(*executionEnvironment->rootDeviceEnvironments[0]);
auto xeIoctlHelper = static_cast<MockIoctlHelperXe *>(drm->getIoctlHelper());
uint64_t fenceAddress = 0x4321;
uint64_t fenceValue = 0x789;
VmBindExtUserFenceT vmBindExtUserFence{};
xeIoctlHelper->fillVmBindExtUserFence(vmBindExtUserFence, fenceAddress, fenceValue, 0u);
VmBindParams vmBindParams{};
vmBindParams.handle = 0x1234;
vmBindParams.start = 0x0;
vmBindParams.length = 0x0;
vmBindParams.sharedSystemUsmEnabled = false;
xeIoctlHelper->setVmBindUserFence(vmBindParams, vmBindExtUserFence);
drm->vmBindInputs.clear();
drm->syncInputs.clear();
drm->waitUserFenceInputs.clear();
StreamCapture capture;
capture.captureStderr();
debugManager.flags.PrintXeLogs.set(true);
ASSERT_EQ(0, xeIoctlHelper->vmUnbind(vmBindParams));
debugManager.flags.PrintXeLogs.set(false);
std::string output = capture.getCapturedStderr();
std::string expectedOutput = "vm=0 obj=0x0 off=0x0 range=0x0 addr=0x0 operation=1(UNMAP) flags=0() nsy=1 num_bind=1";
EXPECT_NE(std::string::npos, output.find(expectedOutput));
EXPECT_EQ(drm->vmBindInputs[0].num_binds, 1u);
EXPECT_EQ(drm->vmBindInputs[0].vector_of_binds, 0u);
}
TEST_F(IoctlHelperXeTest, whenCallingVmUnbindAndSharedSystemAddressRangeExceededThenOneBindOps) {
DebugManagerStateRestore restorer;
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
auto drm = DrmMockXe::create(*executionEnvironment->rootDeviceEnvironments[0]);
auto xeIoctlHelper = static_cast<MockIoctlHelperXe *>(drm->getIoctlHelper());
uint64_t fenceAddress = 0x4321;
uint64_t fenceValue = 0x789;
VmBindExtUserFenceT vmBindExtUserFence{};
xeIoctlHelper->fillVmBindExtUserFence(vmBindExtUserFence, fenceAddress, fenceValue, 0u);
VmBindParams vmBindParams{};
vmBindParams.handle = 0x1234;
vmBindParams.sharedSystemUsmEnabled = true;
vmBindParams.start = 0x1000;
vmBindParams.length = 0x1000;
xeIoctlHelper->setVmBindUserFence(vmBindParams, vmBindExtUserFence);
drm->vmBindInputs.clear();
drm->syncInputs.clear();
drm->waitUserFenceInputs.clear();
StreamCapture capture;
capture.captureStderr();
debugManager.flags.PrintXeLogs.set(true);
ASSERT_EQ(0, xeIoctlHelper->vmUnbind(vmBindParams));
debugManager.flags.PrintXeLogs.set(false);
std::string output = capture.getCapturedStderr();
std::string expectedOutput = "vm=0 obj=0x0 off=0x0 range=0x1000 addr=0x1000 operation=1(UNMAP) flags=0() nsy=1 num_bind=1";
EXPECT_NE(std::string::npos, output.find(expectedOutput));
EXPECT_EQ(drm->vmBindInputs[0].num_binds, 1u);
EXPECT_EQ(drm->vmBindInputs[0].vector_of_binds, 0u);
}
TEST_F(IoctlHelperXeTest, whenCallingVmUnbindAndSharedSystemUsmEnabledThenTwoBindOps) {
DebugManagerStateRestore restorer;
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
auto drm = DrmMockXe::create(*executionEnvironment->rootDeviceEnvironments[0]);
auto xeIoctlHelper = static_cast<MockIoctlHelperXe *>(drm->getIoctlHelper());
uint64_t fenceAddress = 0x4321;
uint64_t fenceValue = 0x789;
VmBindExtUserFenceT vmBindExtUserFence{};
xeIoctlHelper->fillVmBindExtUserFence(vmBindExtUserFence, fenceAddress, fenceValue, 0u);
VmBindParams vmBindParams{};
vmBindParams.handle = 0x1234;
vmBindParams.sharedSystemUsmEnabled = true;
vmBindParams.start = 0x0;
vmBindParams.length = 0x0;
xeIoctlHelper->setVmBindUserFence(vmBindParams, vmBindExtUserFence);
drm->vmBindInputs.clear();
drm->syncInputs.clear();
drm->waitUserFenceInputs.clear();
StreamCapture capture;
capture.captureStderr();
debugManager.flags.PrintXeLogs.set(true);
ASSERT_EQ(0, xeIoctlHelper->vmUnbind(vmBindParams));
debugManager.flags.PrintXeLogs.set(false);
std::string output = capture.getCapturedStderr();
std::string expectedOutput = "vm=0 obj=0x0 off=0x0 range=0x0 addr=0x0 operation[0]=1(UNMAP) flags[0]=0() operation[1]=0(MAP) flags[1]=32(CPU_ADDR_MIRROR) nsy=1 num_bind=2";
EXPECT_NE(std::string::npos, output.find(expectedOutput));
EXPECT_EQ(drm->vmBindInputs[0].num_binds, 2u);
EXPECT_NE(drm->vmBindInputs[0].vector_of_binds, 0u);
}
TEST_F(IoctlHelperXeTest, whenCallingVmbBindWithMadviseAutoResetFlagThenVerifyXeLog) {
DebugManagerStateRestore restorer;
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
auto drm = DrmMockXe::create(*executionEnvironment->rootDeviceEnvironments[0]);
auto xeIoctlHelper = static_cast<MockIoctlHelperXe *>(drm->getIoctlHelper());
uint64_t fenceAddress = 0x4321;
uint64_t fenceValue = 0x789;
VmBindExtUserFenceT vmBindExtUserFence{};
xeIoctlHelper->fillVmBindExtUserFence(vmBindExtUserFence, fenceAddress, fenceValue, 0u);
VmBindParams vmBindParams{};
vmBindParams.flags = DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR | DRM_XE_VM_BIND_FLAG_MADVISE_AUTORESET;
vmBindParams.handle = 0x1234;
xeIoctlHelper->setVmBindUserFence(vmBindParams, vmBindExtUserFence);
drm->vmBindInputs.clear();
drm->syncInputs.clear();
drm->waitUserFenceInputs.clear();
StreamCapture capture;
capture.captureStderr();
debugManager.flags.PrintXeLogs.set(true);
ASSERT_EQ(0, xeIoctlHelper->vmBind(vmBindParams));
debugManager.flags.PrintXeLogs.set(false);
std::string output = capture.getCapturedStderr();
std::string expectedOutput = "vm=0 obj=0x1234 off=0x0 range=0x0 addr=0x0 operation=0(MAP) flags=96(CPU_ADDR_MIRROR MADVISE_AUTORESET) nsy=1 num_bind=1";
EXPECT_NE(std::string::npos, output.find(expectedOutput));
EXPECT_EQ(drm->vmBindInputs[0].num_binds, 1u);
EXPECT_EQ(drm->vmBindInputs[0].vector_of_binds, 0u);
}
TEST_F(IoctlHelperXeTest, whenBindingDrmContextWithoutVirtualEnginesThenProperEnginesAreSelected) {
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
auto drm = DrmMockXe::create(*executionEnvironment->rootDeviceEnvironments[0]);