From d3baab00db172b29bf2e7531d4eca5969392b7a8 Mon Sep 17 00:00:00 2001 From: Brandon Yates Date: Tue, 9 Jan 2024 13:40:40 +0000 Subject: [PATCH] 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 --- .../xe/debug_session_fixtures_linux_xe.cpp | 3 +- .../xe/debug_session_fixtures_linux_xe.h | 2 +- shared/source/os_interface/linux/drm_debug.h | 1 + .../os_interface/linux/xe/ioctl_helper_xe.cpp | 10 ++ .../os_interface/linux/xe/ioctl_helper_xe.h | 13 ++ .../linux/xe/ioctl_helper_xe_debugger.cpp | 78 ++++++++++++ shared/test/common/mocks/CMakeLists.txt | 1 + .../common/mocks/linux}/debug_mock_drm_xe.h | 17 ++- .../xe/ioctl_helper_xe_debugger_tests.cpp | 116 +++++++++++++++++- .../linux/xe/ioctl_helper_xe_tests.h | 1 + 10 files changed, 237 insertions(+), 5 deletions(-) rename {level_zero/tools/test/unit_tests/sources/debug/linux/xe => shared/test/common/mocks/linux}/debug_mock_drm_xe.h (82%) diff --git a/level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_session_fixtures_linux_xe.cpp b/level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_session_fixtures_linux_xe.cpp index 736b5a0dbd..4f057a34d7 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_session_fixtures_linux_xe.cpp +++ b/level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_session_fixtures_linux_xe.cpp @@ -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 { diff --git a/level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_session_fixtures_linux_xe.h b/level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_session_fixtures_linux_xe.h index f6f71fe4f7..b0fd654465 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_session_fixtures_linux_xe.h +++ b/level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_session_fixtures_linux_xe.h @@ -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" diff --git a/shared/source/os_interface/linux/drm_debug.h b/shared/source/os_interface/linux/drm_debug.h index 4ee506470f..281f02622b 100644 --- a/shared/source/os_interface/linux/drm_debug.h +++ b/shared/source/os_interface/linux/drm_debug.h @@ -21,6 +21,7 @@ enum class DrmResourceClass : uint32_t { sbaTrackingBuffer, contextID, l0ZebinModule, + cookie, maxSize }; diff --git a/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp b/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp index 7d0702dee9..ebb1c767fa 100644 --- a/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp +++ b/shared/source/os_interface/linux/xe/ioctl_helper_xe.cpp @@ -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(allocateDebugMetadata()); + } ret = IoctlHelper::ioctl(request, &args); + if (drm.getRootDeviceEnvironment().executionEnvironment.getDebuggingMode() != DebuggingMode::disabled) { + args.extensions = reinterpret_cast(freeDebugMetadata(reinterpret_cast(args.extensions))); + } + d->vmId = ret ? 0 : args.vm_id; d->flags = ret ? 0 : args.flags; xeVmId = d->vmId; diff --git a/shared/source/os_interface/linux/xe/ioctl_helper_xe.h b/shared/source/os_interface/linux/xe/ioctl_helper_xe.h index eddfdd41a5..78b4c7d2da 100644 --- a/shared/source/os_interface/linux/xe/ioctl_helper_xe.h +++ b/shared/source/os_interface/linux/xe/ioctl_helper_xe.h @@ -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 @@ -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; + private: template void xeLog(XeLogArgs &&...args) const; diff --git a/shared/source/os_interface/linux/xe/ioctl_helper_xe_debugger.cpp b/shared/source/os_interface/linux/xe/ioctl_helper_xe_debugger.cpp index f74327a3ff..de8b646d79 100644 --- a/shared/source/os_interface/linux/xe/ioctl_helper_xe_debugger.cpp +++ b/shared/source/os_interface/linux/xe/ioctl_helper_xe_debugger.cpp @@ -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(xeMetadata); + } + prev = xeMetadata; + } + return xeMetadataRoot; +} + +void *IoctlHelperXe::freeDebugMetadata(void *metadata) { + xe_user_extension *ext = static_cast(metadata); + xe_user_extension *prev = nullptr; + xe_user_extension *newRoot = nullptr; + while (ext) { + xe_user_extension *temp = reinterpret_cast(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(offset), size, false}; + debugMetadata.push_back(metadata); + return; +} + } // namespace NEO \ No newline at end of file diff --git a/shared/test/common/mocks/CMakeLists.txt b/shared/test/common/mocks/CMakeLists.txt index 6a2121bdad..048bb2b6f0 100644 --- a/shared/test/common/mocks/CMakeLists.txt +++ b/shared/test/common/mocks/CMakeLists.txt @@ -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) diff --git a/level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_mock_drm_xe.h b/shared/test/common/mocks/linux/debug_mock_drm_xe.h similarity index 82% rename from level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_mock_drm_xe.h rename to shared/test/common/mocks/linux/debug_mock_drm_xe.h index 30307f06a8..089f24fbb2 100644 --- a/level_zero/tools/test/unit_tests/sources/debug/linux/xe/debug_mock_drm_xe.h +++ b/shared/test/common/mocks/linux/debug_mock_drm_xe.h @@ -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(arg); + drm_xe_ext_vm_set_debug_metadata *metadata = reinterpret_cast(v->extensions); + while (metadata) { + vmCreateMetadata.push_back(*metadata); + metadata = reinterpret_cast(metadata->base.next_extension); + } + ret = 0; + } break; case DrmIoctl::debuggerOpen: { auto debuggerOpen = reinterpret_cast(arg); @@ -107,6 +121,7 @@ class DrmMockXeDebug : public DrmMockCustom { int gemVmBindReturn = 0; alignas(64) std::vector queryTopology; + std::vector vmCreateMetadata; // Debugger ioctls int debuggerOpenRetval = 10; // debugFd diff --git a/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_debugger_tests.cpp b/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_debugger_tests.cpp index 386ea8e301..62ff305861 100644 --- a/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_debugger_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_debugger_tests.cpp @@ -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); -} \ No newline at end of file +} + +TEST(IoctlHelperXeTest, givenIoctlHelperXeWhenCallingaddDebugMetadataThenDataIsAdded) { + auto executionEnvironment = std::make_unique(); + DrmMockXeDebug drm{*executionEnvironment->rootDeviceEnvironments[0]}; + auto xeIoctlHelper = std::make_unique(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(); + executionEnvironment->setDebuggingMode(DebuggingMode::offline); + DrmMockXeDebug drm{*executionEnvironment->rootDeviceEnvironments[0]}; + auto xeIoctlHelper = std::make_unique(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(DRM_XE_VM_DEBUG_METADATA_MODULE_AREA)); + ASSERT_EQ(drm.vmCreateMetadata[0].offset, reinterpret_cast(&temp)); + ASSERT_EQ(drm.vmCreateMetadata[0].len, 8000ul); + + ASSERT_EQ(drm.vmCreateMetadata[1].type, static_cast(DRM_XE_VM_DEBUG_METADATA_SIP_AREA)); + ASSERT_EQ(drm.vmCreateMetadata[1].offset, reinterpret_cast(&temp)); + ASSERT_EQ(drm.vmCreateMetadata[1].len, 8000ul); + + ASSERT_EQ(drm.vmCreateMetadata[2].type, static_cast(DRM_XE_VM_DEBUG_METADATA_SBA_AREA)); + ASSERT_EQ(drm.vmCreateMetadata[2].offset, reinterpret_cast(&temp)); + ASSERT_EQ(drm.vmCreateMetadata[2].len, 8000ul); + + ASSERT_EQ(drm.vmCreateMetadata[3].type, static_cast(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(); + executionEnvironment->setDebuggingMode(DebuggingMode::offline); + DrmMockXeDebug drm{*executionEnvironment->rootDeviceEnvironments[0]}; + auto xeIoctlHelper = std::make_unique(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(node2); + node2->base.next_extension = reinterpret_cast(node3); + + drm_xe_ext_vm_set_debug_metadata *newRoot = static_cast(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(node2); + node2->base.next_extension = reinterpret_cast(node3); + + newRoot = static_cast(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(node2); + node2->base.next_extension = reinterpret_cast(node3); + + newRoot = static_cast(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(node2); + node2->base.next_extension = reinterpret_cast(node3); + + newRoot = static_cast(xeIoctlHelper->freeDebugMetadata(node1)); + ASSERT_EQ(newRoot, node1); + ASSERT_EQ(newRoot->base.next_extension, reinterpret_cast(node2)); + delete node1; + delete node2; + delete node3; +} diff --git a/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_tests.h b/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_tests.h index 6e02eaa709..f37f47845a 100644 --- a/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_tests.h +++ b/shared/test/unit_test/os_interface/linux/xe/ioctl_helper_xe_tests.h @@ -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;