feature: Register resources for Xe at vm creation (1/x)

Add interfaces to IoctlHelperXe for registering resources.
Introduce new debug key EnableXeResourceRegistration to attach
resources to vm_create ioctl.

Related-to: NEO-9161
Signed-off-by: Brandon Yatse <brandon.yates@intel.com>
This commit is contained in:
Brandon Yates 2024-01-09 13:40:40 +00:00 committed by Compute-Runtime-Automation
parent 0aee72f1fc
commit d3baab00db
10 changed files with 237 additions and 5 deletions

View File

@ -8,11 +8,10 @@
#include "level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_session_fixtures_linux_xe.h"
#include "shared/test/common/helpers/variable_backup.h"
#include "shared/test/common/mocks/linux/debug_mock_drm_xe.h"
#include "shared/test/common/mocks/mock_device.h"
#include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h"
#include "level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_mock_drm_xe.h"
namespace L0 {
namespace ult {

View File

@ -11,6 +11,7 @@
#include "shared/test/common/helpers/gtest_helpers.h"
#include "shared/test/common/libult/linux/drm_mock_helper.h"
#include "shared/test/common/libult/linux/drm_query_mock.h"
#include "shared/test/common/mocks/linux/debug_mock_drm_xe.h"
#include "shared/test/common/mocks/mock_sip.h"
#include "shared/test/common/mocks/ult_device_factory.h"
#include "shared/test/common/test_macros/test.h"
@ -20,7 +21,6 @@
#include "level_zero/core/test/unit_tests/mocks/mock_built_ins.h"
#include "level_zero/tools/source/debug/linux/xe/debug_session.h"
#include "level_zero/tools/test/unit_tests/sources/debug/debug_session_common.h"
#include "level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_mock_drm_xe.h"
#include "common/StateSaveAreaHeader.h"
#include "uapi-eudebug/drm/xe_drm.h"

View File

@ -21,6 +21,7 @@ enum class DrmResourceClass : uint32_t {
sbaTrackingBuffer,
contextID,
l0ZebinModule,
cookie,
maxSize
};

View File

@ -8,6 +8,8 @@
#include "shared/source/os_interface/linux/xe/ioctl_helper_xe.h"
#include "shared/source/command_stream/csr_definitions.h"
#include "shared/source/debugger/debugger.h"
#include "shared/source/execution_environment/execution_environment.h"
#include "shared/source/execution_environment/root_device_environment.h"
#include "shared/source/gmm_helper/gmm_helper.h"
#include "shared/source/helpers/basic_math.h"
@ -1076,7 +1078,15 @@ int IoctlHelperXe::ioctl(DrmIoctl request, void *arg) {
if (drm.hasPageFaultSupport()) {
args.flags |= DRM_XE_VM_CREATE_FLAG_FAULT_MODE;
}
if (drm.getRootDeviceEnvironment().executionEnvironment.getDebuggingMode() != DebuggingMode::disabled) {
args.extensions = reinterpret_cast<unsigned long long>(allocateDebugMetadata());
}
ret = IoctlHelper::ioctl(request, &args);
if (drm.getRootDeviceEnvironment().executionEnvironment.getDebuggingMode() != DebuggingMode::disabled) {
args.extensions = reinterpret_cast<unsigned long long>(freeDebugMetadata(reinterpret_cast<void *>(args.extensions)));
}
d->vmId = ret ? 0 : args.vm_id;
d->flags = ret ? 0 : args.flags;
xeVmId = d->vmId;

View File

@ -7,6 +7,7 @@
#pragma once
#include "shared/source/debug_settings/debug_settings_manager.h"
#include "shared/source/os_interface/linux/drm_debug.h"
#include "shared/source/os_interface/linux/ioctl_helper.h"
#include <bitset>
@ -124,6 +125,8 @@ class IoctlHelperXe : public IoctlHelper {
void logExecBuffer(const ExecBuffer &execBuffer, std::stringstream &logger) override;
bool setDomainCpu(uint32_t handle, bool writeEnable) override;
uint16_t getCpuCachingMode();
void addDebugMetadata(DrmResourceClass type, uint64_t *offset, uint64_t size);
void addDebugMetadataCookie(uint64_t cookie);
protected:
const char *xeGetClassName(int className);
@ -137,6 +140,8 @@ class IoctlHelperXe : public IoctlHelper {
int xeVmBind(const VmBindParams &vmBindParams, bool bindOp);
void xeShowBindTable();
void updateBindInfo(uint32_t handle, uint64_t userPtr, uint64_t size);
void *allocateDebugMetadata();
void *freeDebugMetadata(void *metadata);
struct UserFenceExtension {
static constexpr uint32_t tagValue = 0x123987;
@ -164,6 +169,14 @@ class IoctlHelperXe : public IoctlHelper {
drm_xe_engine_class_instance *defaultEngine = nullptr;
struct DebugMetadata {
DrmResourceClass type;
uint64_t offset;
uint64_t size;
bool isCookie;
};
std::vector<DebugMetadata> debugMetadata;
private:
template <typename... XeLogArgs>
void xeLog(XeLogArgs &&...args) const;

View File

@ -26,4 +26,82 @@ unsigned int IoctlHelperXe::getIoctlRequestValueDebugger(DrmIoctl ioctlRequest)
}
}
void *IoctlHelperXe::allocateDebugMetadata() {
drm_xe_ext_vm_set_debug_metadata *prev = nullptr;
drm_xe_ext_vm_set_debug_metadata *xeMetadataRoot = nullptr;
for (auto metadata : debugMetadata) {
auto *xeMetadata = new drm_xe_ext_vm_set_debug_metadata();
if (!xeMetadataRoot) {
xeMetadataRoot = xeMetadata;
}
xeMetadata->base.name = DRM_XE_VM_EXTENSION_SET_DEBUG_METADATA;
xeMetadata->offset = metadata.offset;
xeMetadata->len = metadata.size;
if (metadata.isCookie) {
xeMetadata->type = DRM_XE_VM_DEBUG_METADATA_COOKIE;
} else {
switch (metadata.type) {
case DrmResourceClass::contextSaveArea:
xeMetadata->type = DRM_XE_VM_DEBUG_METADATA_SIP_AREA;
break;
case DrmResourceClass::sbaTrackingBuffer:
xeMetadata->type = DRM_XE_VM_DEBUG_METADATA_SBA_AREA;
break;
case DrmResourceClass::moduleHeapDebugArea:
xeMetadata->type = DRM_XE_VM_DEBUG_METADATA_MODULE_AREA;
break;
default:
UNRECOVERABLE_IF(true);
}
}
PRINT_DEBUGGER_INFO_LOG("drm_xe_ext_vm_set_debug_metadata: type = %ul, offset = %ul, len = %ul\n", xeMetadata->type, xeMetadata->offset, xeMetadata->len);
if (prev) {
prev->base.next_extension = reinterpret_cast<unsigned long long>(xeMetadata);
}
prev = xeMetadata;
}
return xeMetadataRoot;
}
void *IoctlHelperXe::freeDebugMetadata(void *metadata) {
xe_user_extension *ext = static_cast<xe_user_extension *>(metadata);
xe_user_extension *prev = nullptr;
xe_user_extension *newRoot = nullptr;
while (ext) {
xe_user_extension *temp = reinterpret_cast<xe_user_extension *>(ext->next_extension);
if (ext->name == DRM_XE_VM_EXTENSION_SET_DEBUG_METADATA) {
if (prev) {
prev->next_extension = ext->next_extension;
}
delete ext;
} else {
if (!newRoot) {
newRoot = ext;
}
prev = ext;
}
ext = temp;
}
return newRoot;
}
void IoctlHelperXe::addDebugMetadataCookie(uint64_t cookie) {
DebugMetadata metadata = {DrmResourceClass::cookie, cookie, 0, true};
debugMetadata.push_back(metadata);
return;
}
void IoctlHelperXe::addDebugMetadata(DrmResourceClass type, uint64_t *offset, uint64_t size) {
if (type != DrmResourceClass::moduleHeapDebugArea && type != DrmResourceClass::contextSaveArea && type != DrmResourceClass::sbaTrackingBuffer) {
return;
}
DebugMetadata metadata = {type, reinterpret_cast<unsigned long long>(offset), size, false};
debugMetadata.push_back(metadata);
return;
}
} // namespace NEO

View File

@ -112,6 +112,7 @@ else()
${CMAKE_CURRENT_SOURCE_DIR}/linux/mock_drm_wrappers.h
${CMAKE_CURRENT_SOURCE_DIR}/linux/mock_ioctl_helper.h
${CMAKE_CURRENT_SOURCE_DIR}/linux/mock_os_time_linux.h
${CMAKE_CURRENT_SOURCE_DIR}/linux/debug_mock_drm_xe.h
)
endif()
if(WIN32 OR NOT DISABLE_WDDM_LINUX)

View File

@ -28,6 +28,12 @@
using namespace NEO;
struct MockIoctlHelperXeDebug : IoctlHelperXe {
using IoctlHelperXe::debugMetadata;
using IoctlHelperXe::freeDebugMetadata;
using IoctlHelperXe::IoctlHelperXe;
};
inline constexpr int testValueVmId = 0x5764;
inline constexpr int testValueMapOff = 0x7788;
inline constexpr int testValuePrime = 0x4321;
@ -53,7 +59,15 @@ class DrmMockXeDebug : public DrmMockCustom {
return setIoctlAnswer;
}
switch (request) {
case DrmIoctl::gemVmCreate: {
struct drm_xe_vm_create *v = static_cast<struct drm_xe_vm_create *>(arg);
drm_xe_ext_vm_set_debug_metadata *metadata = reinterpret_cast<drm_xe_ext_vm_set_debug_metadata *>(v->extensions);
while (metadata) {
vmCreateMetadata.push_back(*metadata);
metadata = reinterpret_cast<drm_xe_ext_vm_set_debug_metadata *>(metadata->base.next_extension);
}
ret = 0;
} break;
case DrmIoctl::debuggerOpen: {
auto debuggerOpen = reinterpret_cast<drm_xe_eudebug_connect *>(arg);
@ -107,6 +121,7 @@ class DrmMockXeDebug : public DrmMockCustom {
int gemVmBindReturn = 0;
alignas(64) std::vector<uint8_t> queryTopology;
std::vector<drm_xe_ext_vm_set_debug_metadata> vmCreateMetadata;
// Debugger ioctls
int debuggerOpenRetval = 10; // debugFd

View File

@ -9,6 +9,7 @@
#include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "shared/test/common/helpers/default_hw_info.h"
#include "shared/test/common/libult/linux/drm_mock.h"
#include "shared/test/common/mocks/linux/debug_mock_drm_xe.h"
#include "shared/test/common/mocks/linux/mock_os_time_linux.h"
#include "shared/test/common/mocks/mock_execution_environment.h"
#include "shared/test/common/test_macros/test.h"
@ -32,4 +33,117 @@ TEST(IoctlHelperXeTest, givenIoctlHelperXeWhenCallingGetIoctForDebuggerThenCorre
verifyIoctlString(DrmIoctl::debuggerOpen, "DRM_IOCTL_XE_EUDEBUG_CONNECT");
verifyIoctlRequestValue(DRM_IOCTL_XE_EUDEBUG_CONNECT, DrmIoctl::debuggerOpen);
}
}
TEST(IoctlHelperXeTest, givenIoctlHelperXeWhenCallingaddDebugMetadataThenDataIsAdded) {
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
DrmMockXeDebug drm{*executionEnvironment->rootDeviceEnvironments[0]};
auto xeIoctlHelper = std::make_unique<MockIoctlHelperXeDebug>(drm);
uint64_t temp = 0;
xeIoctlHelper->addDebugMetadata(DrmResourceClass::moduleHeapDebugArea, &temp, 8000u);
ASSERT_EQ(1u, xeIoctlHelper->debugMetadata.size());
xeIoctlHelper->addDebugMetadata(DrmResourceClass::contextSaveArea, &temp, 8000u);
ASSERT_EQ(2u, xeIoctlHelper->debugMetadata.size());
xeIoctlHelper->addDebugMetadata(DrmResourceClass::sbaTrackingBuffer, &temp, 8000u);
ASSERT_EQ(3u, xeIoctlHelper->debugMetadata.size());
xeIoctlHelper->addDebugMetadata(DrmResourceClass::isa, &temp, 8000u); // ISA should be ignored
ASSERT_EQ(3u, xeIoctlHelper->debugMetadata.size());
}
TEST(IoctlHelperXeTest, givenIoctlHelperXeWhenCallingVmCreateThenDebugMetadadaIsAttached) {
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
executionEnvironment->setDebuggingMode(DebuggingMode::offline);
DrmMockXeDebug drm{*executionEnvironment->rootDeviceEnvironments[0]};
auto xeIoctlHelper = std::make_unique<MockIoctlHelperXeDebug>(drm);
uint64_t temp = 0;
xeIoctlHelper->addDebugMetadata(DrmResourceClass::moduleHeapDebugArea, &temp, 8000u);
xeIoctlHelper->addDebugMetadata(DrmResourceClass::contextSaveArea, &temp, 8000u);
xeIoctlHelper->addDebugMetadata(DrmResourceClass::sbaTrackingBuffer, &temp, 8000u);
xeIoctlHelper->addDebugMetadata(DrmResourceClass::isa, &temp, 8000u); // ISA should be ignored
xeIoctlHelper->addDebugMetadataCookie(123u);
GemVmControl test = {};
xeIoctlHelper->ioctl(DrmIoctl::gemVmCreate, &test);
ASSERT_EQ(4u, drm.vmCreateMetadata.size());
ASSERT_EQ(drm.vmCreateMetadata[0].type, static_cast<unsigned long long>(DRM_XE_VM_DEBUG_METADATA_MODULE_AREA));
ASSERT_EQ(drm.vmCreateMetadata[0].offset, reinterpret_cast<unsigned long long>(&temp));
ASSERT_EQ(drm.vmCreateMetadata[0].len, 8000ul);
ASSERT_EQ(drm.vmCreateMetadata[1].type, static_cast<unsigned long long>(DRM_XE_VM_DEBUG_METADATA_SIP_AREA));
ASSERT_EQ(drm.vmCreateMetadata[1].offset, reinterpret_cast<unsigned long long>(&temp));
ASSERT_EQ(drm.vmCreateMetadata[1].len, 8000ul);
ASSERT_EQ(drm.vmCreateMetadata[2].type, static_cast<unsigned long long>(DRM_XE_VM_DEBUG_METADATA_SBA_AREA));
ASSERT_EQ(drm.vmCreateMetadata[2].offset, reinterpret_cast<unsigned long long>(&temp));
ASSERT_EQ(drm.vmCreateMetadata[2].len, 8000ul);
ASSERT_EQ(drm.vmCreateMetadata[3].type, static_cast<unsigned long long>(DRM_XE_VM_DEBUG_METADATA_COOKIE));
ASSERT_EQ(drm.vmCreateMetadata[3].offset, 123ul);
ASSERT_EQ(drm.vmCreateMetadata[3].len, 0ul);
ASSERT_EQ(drm.vmCreateMetadata[3].base.next_extension, 0ul);
}
TEST(IoctlHelperXeTest, givenFreeDebugMetadataWhenVmCreateHasMultipleExtTypesThenOnlyDebugMetadataIsDeleted) {
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
executionEnvironment->setDebuggingMode(DebuggingMode::offline);
DrmMockXeDebug drm{*executionEnvironment->rootDeviceEnvironments[0]};
auto xeIoctlHelper = std::make_unique<MockIoctlHelperXeDebug>(drm);
drm_xe_ext_vm_set_debug_metadata *node1 = new drm_xe_ext_vm_set_debug_metadata();
drm_xe_ext_vm_set_debug_metadata *node2 = new drm_xe_ext_vm_set_debug_metadata();
drm_xe_ext_vm_set_debug_metadata *node3 = new drm_xe_ext_vm_set_debug_metadata();
node1->base.name = DRM_XE_VM_EXTENSION_SET_DEBUG_METADATA;
node2->base.name = 0x1234ul;
node3->base.name = DRM_XE_VM_EXTENSION_SET_DEBUG_METADATA;
node1->base.next_extension = reinterpret_cast<unsigned long long>(node2);
node2->base.next_extension = reinterpret_cast<unsigned long long>(node3);
drm_xe_ext_vm_set_debug_metadata *newRoot = static_cast<drm_xe_ext_vm_set_debug_metadata *>(xeIoctlHelper->freeDebugMetadata(node1));
ASSERT_EQ(newRoot, node2);
ASSERT_EQ(newRoot->base.next_extension, 0ul);
delete node2;
node1 = new drm_xe_ext_vm_set_debug_metadata();
node2 = new drm_xe_ext_vm_set_debug_metadata();
node3 = new drm_xe_ext_vm_set_debug_metadata();
node1->base.name = DRM_XE_VM_EXTENSION_SET_DEBUG_METADATA;
node2->base.name = DRM_XE_VM_EXTENSION_SET_DEBUG_METADATA;
node3->base.name = DRM_XE_VM_EXTENSION_SET_DEBUG_METADATA;
node1->base.next_extension = reinterpret_cast<unsigned long long>(node2);
node2->base.next_extension = reinterpret_cast<unsigned long long>(node3);
newRoot = static_cast<drm_xe_ext_vm_set_debug_metadata *>(xeIoctlHelper->freeDebugMetadata(node1));
ASSERT_EQ(newRoot, nullptr);
node1 = new drm_xe_ext_vm_set_debug_metadata();
node2 = new drm_xe_ext_vm_set_debug_metadata();
node3 = new drm_xe_ext_vm_set_debug_metadata();
node1->base.name = 0x1234;
node2->base.name = DRM_XE_VM_EXTENSION_SET_DEBUG_METADATA;
node3->base.name = DRM_XE_VM_EXTENSION_SET_DEBUG_METADATA;
node1->base.next_extension = reinterpret_cast<unsigned long long>(node2);
node2->base.next_extension = reinterpret_cast<unsigned long long>(node3);
newRoot = static_cast<drm_xe_ext_vm_set_debug_metadata *>(xeIoctlHelper->freeDebugMetadata(node1));
ASSERT_EQ(newRoot, node1);
ASSERT_EQ(newRoot->base.next_extension, 0ul);
delete node1;
node1 = new drm_xe_ext_vm_set_debug_metadata();
node2 = new drm_xe_ext_vm_set_debug_metadata();
node3 = new drm_xe_ext_vm_set_debug_metadata();
node1->base.name = 0x1234;
node2->base.name = 0x1234;
node3->base.name = 0x1234;
node1->base.next_extension = reinterpret_cast<unsigned long long>(node2);
node2->base.next_extension = reinterpret_cast<unsigned long long>(node3);
newRoot = static_cast<drm_xe_ext_vm_set_debug_metadata *>(xeIoctlHelper->freeDebugMetadata(node1));
ASSERT_EQ(newRoot, node1);
ASSERT_EQ(newRoot->base.next_extension, reinterpret_cast<unsigned long long>(node2));
delete node1;
delete node2;
delete node3;
}

View File

@ -28,6 +28,7 @@ using namespace NEO;
struct MockIoctlHelperXe : IoctlHelperXe {
using IoctlHelperXe::bindInfo;
using IoctlHelperXe::debugMetadata;
using IoctlHelperXe::defaultEngine;
using IoctlHelperXe::getFdFromVmExport;
using IoctlHelperXe::IoctlHelperXe;