From b6c096e5e6f4f0a5adc67a6bd8d51418e06464c0 Mon Sep 17 00:00:00 2001 From: Krzysztof Swiecicki Date: Mon, 12 Jan 2026 10:40:38 +0000 Subject: [PATCH 1/4] [UR] Define exp-usm-host-alloc-register.yml spec --- unified-runtime/include/ur_api.h | 113 +++++++++++ unified-runtime/include/ur_api_funcs.def | 2 + unified-runtime/include/ur_ddi.h | 13 ++ unified-runtime/include/ur_print.h | 40 ++++ unified-runtime/include/ur_print.hpp | 177 ++++++++++++++++++ .../core/EXP-USM-HOST-ALLOC-REGISTER.rst | 67 +++++++ .../core/exp-usm-host-alloc-register.yml | 94 ++++++++++ unified-runtime/scripts/core/registry.yml | 8 +- .../level_zero/ur_interface_loader.cpp | 4 + .../level_zero/ur_interface_loader.hpp | 5 + .../source/adapters/mock/ur_mockddi.cpp | 98 ++++++++++ .../source/common/stype_map_helpers.def | 4 + .../loader/layers/tracing/ur_trcddi.cpp | 91 +++++++++ .../loader/layers/validation/ur_valddi.cpp | 85 +++++++++ unified-runtime/source/loader/loader.def.in | 6 + unified-runtime/source/loader/loader.map.in | 6 + unified-runtime/source/loader/ur_ldrddi.cpp | 44 +++++ unified-runtime/source/loader/ur_libapi.cpp | 68 +++++++ unified-runtime/source/loader/ur_print.cpp | 32 ++++ unified-runtime/source/ur_api.cpp | 56 ++++++ unified-runtime/tools/urinfo/urinfo.hpp | 3 + 21 files changed, 1015 insertions(+), 1 deletion(-) create mode 100644 unified-runtime/scripts/core/EXP-USM-HOST-ALLOC-REGISTER.rst create mode 100644 unified-runtime/scripts/core/exp-usm-host-alloc-register.yml diff --git a/unified-runtime/include/ur_api.h b/unified-runtime/include/ur_api.h index 2b23e3cd0c59e..87e4deea2ad81 100644 --- a/unified-runtime/include/ur_api.h +++ b/unified-runtime/include/ur_api.h @@ -513,6 +513,10 @@ typedef enum ur_function_t { UR_FUNCTION_ENQUEUE_GRAPH_EXP = 308, /// Enumerator for ::urEnqueueHostTaskExp UR_FUNCTION_ENQUEUE_HOST_TASK_EXP = 309, + /// Enumerator for ::urUSMHostAllocRegisterExp + UR_FUNCTION_USM_HOST_ALLOC_REGISTER_EXP = 310, + /// Enumerator for ::urUSMHostAllocUnregisterExp + UR_FUNCTION_USM_HOST_ALLOC_UNREGISTER_EXP = 311, /// @cond UR_FUNCTION_FORCE_UINT32 = 0x7fffffff /// @endcond @@ -636,6 +640,8 @@ typedef enum ur_structure_type_t { UR_STRUCTURE_TYPE_EXP_KERNEL_ARG_PROPERTIES = 0x5000, /// ::ur_exp_host_task_properties_t UR_STRUCTURE_TYPE_EXP_HOST_TASK_PROPERTIES = 0x6000, + /// ::ur_exp_usm_host_alloc_register_properties_t + UR_STRUCTURE_TYPE_EXP_USM_HOST_ALLOC_REGISTER_PROPERTIES = 0x7000, /// @cond UR_STRUCTURE_TYPE_FORCE_UINT32 = 0x7fffffff /// @endcond @@ -2496,6 +2502,9 @@ typedef enum ur_device_info_t { /// [::ur_bool_t] Returns true if the device supports graph record and replay /// functionality. UR_DEVICE_INFO_GRAPH_RECORD_AND_REPLAY_SUPPORT_EXP = 0x2080, + /// [::ur_bool_t] returns true if the device supports registering host + /// memory ranges. + UR_DEVICE_INFO_USM_HOST_ALLOC_REGISTER_SUPPORT_EXP = 0x2090, /// [::ur_bool_t] Returns true if the device supports the USM P2P /// experimental feature. UR_DEVICE_INFO_USM_P2P_SUPPORT_EXP = 0x4000, @@ -12966,6 +12975,90 @@ UR_APIEXPORT ur_result_t UR_APICALL urUSMContextMemcpyExp( /// [in] Size in bytes to be copied. size_t size); +#if !defined(__GNUC__) +#pragma endregion +#endif +// Host Memory Registration Extension Experimental APIs +#if !defined(__GNUC__) +#pragma region usm_host_alloc_register_(experimental) +#endif +/////////////////////////////////////////////////////////////////////////////// +/// @brief USM host memory registration flags. +typedef uint32_t ur_exp_usm_host_alloc_register_flags_t; +typedef enum ur_exp_usm_host_alloc_register_flag_t { + /// Reserved for future use. + UR_EXP_USM_HOST_ALLOC_REGISTER_FLAG_TBD = UR_BIT(0), + /// @cond + UR_EXP_USM_HOST_ALLOC_REGISTER_FLAG_FORCE_UINT32 = 0x7fffffff + /// @endcond + +} ur_exp_usm_host_alloc_register_flag_t; +/// @brief Bit Mask for validating ur_exp_usm_host_alloc_register_flags_t +#define UR_EXP_USM_HOST_ALLOC_REGISTER_FLAGS_MASK 0xfffffffe + +/////////////////////////////////////////////////////////////////////////////// +/// @brief USM host memory registration properties. +typedef struct ur_exp_usm_host_alloc_register_properties_t { + /// [in] type of this structure, must be + /// ::UR_STRUCTURE_TYPE_EXP_USM_HOST_ALLOC_REGISTER_PROPERTIES + ur_structure_type_t stype; + /// [in,out][optional] pointer to extension-specific structure + void *pNext; + /// [in] Host memory registration flags. + ur_exp_usm_host_alloc_register_flags_t flags; + +} ur_exp_usm_host_alloc_register_properties_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Maps a host memory range to make it recognizable by the underlying +/// adapter. The host memory must remain valid throughout the +/// registration lifetime. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pHostMem` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `NULL != pProperties && +/// ::UR_EXP_USM_HOST_ALLOC_REGISTER_FLAGS_MASK & pProperties->flags` +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// + `size == 0` +UR_APIEXPORT ur_result_t UR_APICALL urUSMHostAllocRegisterExp( + /// [in] Handle of the context. + ur_context_handle_t hContext, + /// [in] Pointer to the host memory range to register. + void *pHostMem, + /// [in] Size in bytes of the host memory range to register, must be + /// page-aligned. + size_t size, + /// [in][optional] Pointer to host memory registration properties. + const ur_exp_usm_host_alloc_register_properties_t *pProperties); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Unregister a previously registered host memory range. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pHostMem` +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// + Invalid host memory range. +UR_APIEXPORT ur_result_t UR_APICALL urUSMHostAllocUnregisterExp( + /// [in] Handle of the context. + ur_context_handle_t hContext, + /// [in][release] Pointer to the registered host memory range. + void *pHostMem); + #if !defined(__GNUC__) #pragma endregion #endif @@ -15656,6 +15749,26 @@ typedef struct ur_usm_context_memcpy_exp_params_t { size_t *psize; } ur_usm_context_memcpy_exp_params_t; +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function parameters for urUSMHostAllocUnregisterExp +/// @details Each entry is a pointer to the parameter passed to the function; +/// allowing the callback the ability to modify the parameter's value +typedef struct ur_usm_host_alloc_unregister_exp_params_t { + ur_context_handle_t *phContext; + void **ppHostMem; +} ur_usm_host_alloc_unregister_exp_params_t; + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function parameters for urUSMHostAllocRegisterExp +/// @details Each entry is a pointer to the parameter passed to the function; +/// allowing the callback the ability to modify the parameter's value +typedef struct ur_usm_host_alloc_register_exp_params_t { + ur_context_handle_t *phContext; + void **ppHostMem; + size_t *psize; + const ur_exp_usm_host_alloc_register_properties_t **ppProperties; +} ur_usm_host_alloc_register_exp_params_t; + /////////////////////////////////////////////////////////////////////////////// /// @brief Function parameters for urUSMImportExp /// @details Each entry is a pointer to the parameter passed to the function; diff --git a/unified-runtime/include/ur_api_funcs.def b/unified-runtime/include/ur_api_funcs.def index 0c7fd185cb0f7..69f0a7471a5be 100644 --- a/unified-runtime/include/ur_api_funcs.def +++ b/unified-runtime/include/ur_api_funcs.def @@ -167,6 +167,8 @@ _UR_API(urUSMPoolGetDevicePoolExp) _UR_API(urUSMPoolTrimToExp) _UR_API(urUSMPitchedAllocExp) _UR_API(urUSMContextMemcpyExp) +_UR_API(urUSMHostAllocUnregisterExp) +_UR_API(urUSMHostAllocRegisterExp) _UR_API(urUSMImportExp) _UR_API(urUSMReleaseExp) _UR_API(urBindlessImagesUnsampledImageHandleDestroyExp) diff --git a/unified-runtime/include/ur_ddi.h b/unified-runtime/include/ur_ddi.h index 667b0600db0db..a0dce4166a90a 100644 --- a/unified-runtime/include/ur_ddi.h +++ b/unified-runtime/include/ur_ddi.h @@ -1401,6 +1401,17 @@ typedef ur_result_t(UR_APICALL *ur_pfnUSMPitchedAllocExp_t)( typedef ur_result_t(UR_APICALL *ur_pfnUSMContextMemcpyExp_t)( ur_context_handle_t, void *, const void *, size_t); +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for urUSMHostAllocUnregisterExp +typedef ur_result_t(UR_APICALL *ur_pfnUSMHostAllocUnregisterExp_t)( + ur_context_handle_t, void *); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Function-pointer for urUSMHostAllocRegisterExp +typedef ur_result_t(UR_APICALL *ur_pfnUSMHostAllocRegisterExp_t)( + ur_context_handle_t, void *, size_t, + const ur_exp_usm_host_alloc_register_properties_t *); + /////////////////////////////////////////////////////////////////////////////// /// @brief Function-pointer for urUSMImportExp typedef ur_result_t(UR_APICALL *ur_pfnUSMImportExp_t)(ur_context_handle_t, @@ -1424,6 +1435,8 @@ typedef struct ur_usm_exp_dditable_t { ur_pfnUSMPoolTrimToExp_t pfnPoolTrimToExp; ur_pfnUSMPitchedAllocExp_t pfnPitchedAllocExp; ur_pfnUSMContextMemcpyExp_t pfnContextMemcpyExp; + ur_pfnUSMHostAllocUnregisterExp_t pfnHostAllocUnregisterExp; + ur_pfnUSMHostAllocRegisterExp_t pfnHostAllocRegisterExp; ur_pfnUSMImportExp_t pfnImportExp; ur_pfnUSMReleaseExp_t pfnReleaseExp; } ur_usm_exp_dditable_t; diff --git a/unified-runtime/include/ur_print.h b/unified-runtime/include/ur_print.h index a367339986b91..2bbd5342be12e 100644 --- a/unified-runtime/include/ur_print.h +++ b/unified-runtime/include/ur_print.h @@ -1445,6 +1445,26 @@ UR_APIEXPORT ur_result_t UR_APICALL urPrintExpProgramFlags(enum ur_exp_program_flag_t value, char *buffer, const size_t buff_size, size_t *out_size); +/////////////////////////////////////////////////////////////////////////////// +/// @brief Print ur_exp_usm_host_alloc_register_flag_t enum +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_SIZE +/// - `buff_size < out_size` +UR_APIEXPORT ur_result_t UR_APICALL urPrintExpUsmHostAllocRegisterFlags( + enum ur_exp_usm_host_alloc_register_flag_t value, char *buffer, + const size_t buff_size, size_t *out_size); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Print ur_exp_usm_host_alloc_register_properties_t struct +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_SIZE +/// - `buff_size < out_size` +UR_APIEXPORT ur_result_t UR_APICALL urPrintExpUsmHostAllocRegisterProperties( + const struct ur_exp_usm_host_alloc_register_properties_t params, + char *buffer, const size_t buff_size, size_t *out_size); + /////////////////////////////////////////////////////////////////////////////// /// @brief Print ur_exp_peer_info_t enum /// @returns @@ -3125,6 +3145,26 @@ UR_APIEXPORT ur_result_t UR_APICALL urPrintUsmContextMemcpyExpParams( const struct ur_usm_context_memcpy_exp_params_t *params, char *buffer, const size_t buff_size, size_t *out_size); +/////////////////////////////////////////////////////////////////////////////// +/// @brief Print ur_usm_host_alloc_unregister_exp_params_t struct +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_SIZE +/// - `buff_size < out_size` +UR_APIEXPORT ur_result_t UR_APICALL urPrintUsmHostAllocUnregisterExpParams( + const struct ur_usm_host_alloc_unregister_exp_params_t *params, + char *buffer, const size_t buff_size, size_t *out_size); + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Print ur_usm_host_alloc_register_exp_params_t struct +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_INVALID_SIZE +/// - `buff_size < out_size` +UR_APIEXPORT ur_result_t UR_APICALL urPrintUsmHostAllocRegisterExpParams( + const struct ur_usm_host_alloc_register_exp_params_t *params, char *buffer, + const size_t buff_size, size_t *out_size); + /////////////////////////////////////////////////////////////////////////////// /// @brief Print ur_usm_import_exp_params_t struct /// @returns diff --git a/unified-runtime/include/ur_print.hpp b/unified-runtime/include/ur_print.hpp index 156b27813e09c..57cff77b0a291 100644 --- a/unified-runtime/include/ur_print.hpp +++ b/unified-runtime/include/ur_print.hpp @@ -267,6 +267,11 @@ template <> inline ur_result_t printFlag(std::ostream &os, uint32_t flag); +template <> +inline ur_result_t +printFlag(std::ostream &os, + uint32_t flag); + template <> inline ur_result_t printTagged(std::ostream &os, const void *ptr, ur_exp_peer_info_t value, size_t size); @@ -616,6 +621,12 @@ operator<<(std::ostream &os, [[maybe_unused]] const struct ur_exp_command_buffer_update_kernel_launch_desc_t params); inline std::ostream &operator<<(std::ostream &os, enum ur_exp_program_flag_t value); +inline std::ostream & +operator<<(std::ostream &os, enum ur_exp_usm_host_alloc_register_flag_t value); +inline std::ostream &operator<<( + std::ostream &os, + [[maybe_unused]] const struct ur_exp_usm_host_alloc_register_properties_t + params); inline std::ostream &operator<<(std::ostream &os, enum ur_exp_peer_info_t value); inline std::ostream &operator<<(std::ostream &os, @@ -1370,6 +1381,12 @@ inline std::ostream &operator<<(std::ostream &os, enum ur_function_t value) { case UR_FUNCTION_ENQUEUE_HOST_TASK_EXP: os << "UR_FUNCTION_ENQUEUE_HOST_TASK_EXP"; break; + case UR_FUNCTION_USM_HOST_ALLOC_REGISTER_EXP: + os << "UR_FUNCTION_USM_HOST_ALLOC_REGISTER_EXP"; + break; + case UR_FUNCTION_USM_HOST_ALLOC_UNREGISTER_EXP: + os << "UR_FUNCTION_USM_HOST_ALLOC_UNREGISTER_EXP"; + break; default: os << "unknown enumerator"; break; @@ -1554,6 +1571,9 @@ inline std::ostream &operator<<(std::ostream &os, case UR_STRUCTURE_TYPE_EXP_HOST_TASK_PROPERTIES: os << "UR_STRUCTURE_TYPE_EXP_HOST_TASK_PROPERTIES"; break; + case UR_STRUCTURE_TYPE_EXP_USM_HOST_ALLOC_REGISTER_PROPERTIES: + os << "UR_STRUCTURE_TYPE_EXP_USM_HOST_ALLOC_REGISTER_PROPERTIES"; + break; default: os << "unknown enumerator"; break; @@ -1900,6 +1920,12 @@ inline ur_result_t printStruct(std::ostream &os, const void *ptr) { (const ur_exp_host_task_properties_t *)ptr; printPtr(os, pstruct); } break; + + case UR_STRUCTURE_TYPE_EXP_USM_HOST_ALLOC_REGISTER_PROPERTIES: { + const ur_exp_usm_host_alloc_register_properties_t *pstruct = + (const ur_exp_usm_host_alloc_register_properties_t *)ptr; + printPtr(os, pstruct); + } break; default: os << "unknown enumerator"; return UR_RESULT_ERROR_INVALID_ENUMERATION; @@ -3281,6 +3307,9 @@ inline std::ostream &operator<<(std::ostream &os, enum ur_device_info_t value) { case UR_DEVICE_INFO_GRAPH_RECORD_AND_REPLAY_SUPPORT_EXP: os << "UR_DEVICE_INFO_GRAPH_RECORD_AND_REPLAY_SUPPORT_EXP"; break; + case UR_DEVICE_INFO_USM_HOST_ALLOC_REGISTER_SUPPORT_EXP: + os << "UR_DEVICE_INFO_USM_HOST_ALLOC_REGISTER_SUPPORT_EXP"; + break; case UR_DEVICE_INFO_USM_P2P_SUPPORT_EXP: os << "UR_DEVICE_INFO_USM_P2P_SUPPORT_EXP"; break; @@ -5506,6 +5535,19 @@ inline ur_result_t printTagged(std::ostream &os, const void *ptr, os << ")"; } break; + case UR_DEVICE_INFO_USM_HOST_ALLOC_REGISTER_SUPPORT_EXP: { + const ur_bool_t *tptr = (const ur_bool_t *)ptr; + if (sizeof(ur_bool_t) > size) { + os << "invalid size (is: " << size + << ", expected: >=" << sizeof(ur_bool_t) << ")"; + return UR_RESULT_ERROR_INVALID_SIZE; + } + os << (const void *)(tptr) << " ("; + + os << *tptr; + + os << ")"; + } break; case UR_DEVICE_INFO_USM_P2P_SUPPORT_EXP: { const ur_bool_t *tptr = (const ur_bool_t *)ptr; if (sizeof(ur_bool_t) > size) { @@ -12625,6 +12667,83 @@ inline ur_result_t printFlag(std::ostream &os, } } // namespace ur::details /////////////////////////////////////////////////////////////////////////////// +/// @brief Print operator for the ur_exp_usm_host_alloc_register_flag_t type +/// @returns +/// std::ostream & +inline std::ostream & +operator<<(std::ostream &os, enum ur_exp_usm_host_alloc_register_flag_t value) { + switch (value) { + case UR_EXP_USM_HOST_ALLOC_REGISTER_FLAG_TBD: + os << "UR_EXP_USM_HOST_ALLOC_REGISTER_FLAG_TBD"; + break; + default: + os << "unknown enumerator"; + break; + } + return os; +} + +namespace ur::details { +/////////////////////////////////////////////////////////////////////////////// +/// @brief Print ur_exp_usm_host_alloc_register_flag_t flag +template <> +inline ur_result_t +printFlag(std::ostream &os, + uint32_t flag) { + uint32_t val = flag; + bool first = true; + + if ((val & UR_EXP_USM_HOST_ALLOC_REGISTER_FLAG_TBD) == + (uint32_t)UR_EXP_USM_HOST_ALLOC_REGISTER_FLAG_TBD) { + val ^= (uint32_t)UR_EXP_USM_HOST_ALLOC_REGISTER_FLAG_TBD; + if (!first) { + os << " | "; + } else { + first = false; + } + os << UR_EXP_USM_HOST_ALLOC_REGISTER_FLAG_TBD; + } + if (val != 0) { + std::bitset<32> bits(val); + if (!first) { + os << " | "; + } + os << "unknown bit flags " << bits; + } else if (first) { + os << "0"; + } + return UR_RESULT_SUCCESS; +} +} // namespace ur::details +/////////////////////////////////////////////////////////////////////////////// +/// @brief Print operator for the ur_exp_usm_host_alloc_register_properties_t +/// type +/// @returns +/// std::ostream & +inline std::ostream & +operator<<(std::ostream &os, + const struct ur_exp_usm_host_alloc_register_properties_t params) { + os << "(struct ur_exp_usm_host_alloc_register_properties_t){"; + + os << ".stype = "; + + os << (params.stype); + + os << ", "; + os << ".pNext = "; + + ur::details::printStruct(os, (params.pNext)); + + os << ", "; + os << ".flags = "; + + ur::details::printFlag(os, + (params.flags)); + + os << "}"; + return os; +} +/////////////////////////////////////////////////////////////////////////////// /// @brief Print operator for the ur_exp_peer_info_t type /// @returns /// std::ostream & @@ -18887,6 +19006,58 @@ inline std::ostream &operator<<( return os; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Print operator for the ur_usm_host_alloc_unregister_exp_params_t type +/// @returns +/// std::ostream & +inline std::ostream &operator<<( + std::ostream &os, + [[maybe_unused]] const struct ur_usm_host_alloc_unregister_exp_params_t + *params) { + + os << ".hContext = "; + + ur::details::printPtr(os, *(params->phContext)); + + os << ", "; + os << ".pHostMem = "; + + ur::details::printPtr(os, *(params->ppHostMem)); + + return os; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Print operator for the ur_usm_host_alloc_register_exp_params_t type +/// @returns +/// std::ostream & +inline std::ostream & +operator<<(std::ostream &os, + [[maybe_unused]] const struct ur_usm_host_alloc_register_exp_params_t + *params) { + + os << ".hContext = "; + + ur::details::printPtr(os, *(params->phContext)); + + os << ", "; + os << ".pHostMem = "; + + ur::details::printPtr(os, *(params->ppHostMem)); + + os << ", "; + os << ".size = "; + + os << *(params->psize); + + os << ", "; + os << ".pProperties = "; + + ur::details::printPtr(os, *(params->ppProperties)); + + return os; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Print operator for the ur_usm_import_exp_params_t type /// @returns @@ -22745,6 +22916,12 @@ inline ur_result_t UR_APICALL printFunctionParams(std::ostream &os, case UR_FUNCTION_USM_CONTEXT_MEMCPY_EXP: { os << (const struct ur_usm_context_memcpy_exp_params_t *)params; } break; + case UR_FUNCTION_USM_HOST_ALLOC_UNREGISTER_EXP: { + os << (const struct ur_usm_host_alloc_unregister_exp_params_t *)params; + } break; + case UR_FUNCTION_USM_HOST_ALLOC_REGISTER_EXP: { + os << (const struct ur_usm_host_alloc_register_exp_params_t *)params; + } break; case UR_FUNCTION_USM_IMPORT_EXP: { os << (const struct ur_usm_import_exp_params_t *)params; } break; diff --git a/unified-runtime/scripts/core/EXP-USM-HOST-ALLOC-REGISTER.rst b/unified-runtime/scripts/core/EXP-USM-HOST-ALLOC-REGISTER.rst new file mode 100644 index 0000000000000..4d4d0238d5935 --- /dev/null +++ b/unified-runtime/scripts/core/EXP-USM-HOST-ALLOC-REGISTER.rst @@ -0,0 +1,67 @@ +<% + OneApi=tags['$OneApi'] + x=tags['$x'] + X=x.upper() +%> + +.. _experimental-usm-host-alloc-register: + +================================================================================ +USM Host Alloc Register +================================================================================ + +.. warning:: + + Experimental features: + + * May be replaced, updated, or removed at any time. + * Do not require maintaining API/ABI stability of their own additions over + time. + * Do not require conformance testing of their own additions. + + +Motivation +-------------------------------------------------------------------------------- + +This extension enables applications to register externally-allocated host +memory (such as memory-mapped files or standard malloc allocations) with the +runtime, allowing the device to access it efficiently as USM host memory +without requiring data copies. + +API +-------------------------------------------------------------------------------- + +Enums +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +* ${x}_device_info_t + * ${X}_DEVICE_INFO_USM_HOST_ALLOC_REGISTER_SUPPORT_EXP +* ${x}_structure_type_t + * ${X}_STRUCTURE_TYPE_EXP_USM_HOST_ALLOC_REGISTER_PROPERTIES + +Functions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* ${x}USMHostAllocRegisterExp +* ${x}USMHostAllocUnregisterExp + +Changelog +-------------------------------------------------------------------------------- + ++-----------+---------------------------+ +| Revision | Changes | ++===========+===========================+ +| 1.0 | Initial Draft | ++-----------+---------------------------+ + + +Support +-------------------------------------------------------------------------------- + +Adapters which support this experimental feature *must* return true for the +new ``${X}_DEVICE_INFO_USM_HOST_ALLOC_REGISTER_SUPPORT_EXP`` device info query. + + +Contributors +-------------------------------------------------------------------------------- + +* Krzysztof Swiecicki `krzysztof.swiecicki@intel.com `_ diff --git a/unified-runtime/scripts/core/exp-usm-host-alloc-register.yml b/unified-runtime/scripts/core/exp-usm-host-alloc-register.yml new file mode 100644 index 0000000000000..666de610d1ea6 --- /dev/null +++ b/unified-runtime/scripts/core/exp-usm-host-alloc-register.yml @@ -0,0 +1,94 @@ +# +# Copyright (C) 2026 Intel Corporation +# +# Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM +# Exceptions. +# +# See LICENSE.TXT +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +# +# See YaML.md for syntax definition +# +--- #-------------------------------------------------------------------------- +type: header +desc: "Host Memory Registration Extension Experimental APIs" +ordinal: "99" +--- #-------------------------------------------------------------------------- +type: enum +extend: true +typed_etors: true +desc: "Extension enums to $x_device_info_t to support host memory registration." +name: $x_device_info_t +etors: + - name: USM_HOST_ALLOC_REGISTER_SUPPORT_EXP + value: "0x2090" + desc: |- + [$x_bool_t] returns true if the device supports registering host + memory ranges. +--- #-------------------------------------------------------------------------- +type: enum +desc: "USM host memory registration flags." +name: $x_exp_usm_host_alloc_register_flags_t +etors: + - name: TBD + desc: "Reserved for future use." +--- #-------------------------------------------------------------------------- +type: struct +desc: "USM host memory registration properties." +name: $x_exp_usm_host_alloc_register_properties_t +base: $x_base_properties_t +members: + - type: $x_exp_usm_host_alloc_register_flags_t + name: flags + desc: "[in] Host memory registration flags." +--- #-------------------------------------------------------------------------- +type: enum +extend: true +desc: "Structure type experimental enumerations" +name: $x_structure_type_t +etors: + - name: EXP_USM_HOST_ALLOC_REGISTER_PROPERTIES + desc: $x_exp_usm_host_alloc_register_properties_t + value: "0x7000" +--- #-------------------------------------------------------------------------- +type: function +desc: |- + Maps a host memory range to make it recognizable by the underlying + adapter. The host memory must remain valid throughout the registration + lifetime. +class: $xUSM +name: HostAllocRegisterExp +params: + - type: $x_context_handle_t + name: hContext + desc: "[in] Handle of the context." + - type: void* + name: pHostMem + desc: "[in] Pointer to the host memory range to register." + - type: size_t + name: size + desc: |- + [in] Size in bytes of the host memory range to register, must be + page-aligned. + - type: const $x_exp_usm_host_alloc_register_properties_t* + name: pProperties + desc: "[in][optional] Pointer to host memory registration properties." +returns: + - $X_RESULT_ERROR_INVALID_VALUE: + - "`size == 0`" +--- #-------------------------------------------------------------------------- +type: function +desc: "Unregister a previously registered host memory range." +class: $xUSM +name: HostAllocUnregisterExp +ordinal: "0" +params: + - type: $x_context_handle_t + name: hContext + desc: "[in] Handle of the context." + - type: void* + name: pHostMem + desc: "[in][release] Pointer to the registered host memory range." +returns: + - $X_RESULT_ERROR_INVALID_VALUE: + - "Invalid host memory range." diff --git a/unified-runtime/scripts/core/registry.yml b/unified-runtime/scripts/core/registry.yml index 2ded40ca772c4..ff089889faeeb 100644 --- a/unified-runtime/scripts/core/registry.yml +++ b/unified-runtime/scripts/core/registry.yml @@ -727,7 +727,13 @@ etors: - name: ENQUEUE_HOST_TASK_EXP desc: Enumerator for $xEnqueueHostTaskExp value: '309' -max_id: '309' +- name: USM_HOST_ALLOC_REGISTER_EXP + desc: Enumerator for $xUSMHostAllocRegisterExp + value: '310' +- name: USM_HOST_ALLOC_UNREGISTER_EXP + desc: Enumerator for $xUSMHostAllocUnregisterExp + value: '311' +max_id: '311' --- type: enum desc: Defines structure types diff --git a/unified-runtime/source/adapters/level_zero/ur_interface_loader.cpp b/unified-runtime/source/adapters/level_zero/ur_interface_loader.cpp index d5154018cfada..056dd1266643f 100644 --- a/unified-runtime/source/adapters/level_zero/ur_interface_loader.cpp +++ b/unified-runtime/source/adapters/level_zero/ur_interface_loader.cpp @@ -540,6 +540,10 @@ UR_APIEXPORT ur_result_t UR_APICALL urGetUSMExpProcAddrTable( pDdiTable->pfnPoolTrimToExp = ur::level_zero::urUSMPoolTrimToExp; pDdiTable->pfnPitchedAllocExp = ur::level_zero::urUSMPitchedAllocExp; pDdiTable->pfnContextMemcpyExp = ur::level_zero::urUSMContextMemcpyExp; + pDdiTable->pfnHostAllocUnregisterExp = + ur::level_zero::urUSMHostAllocUnregisterExp; + pDdiTable->pfnHostAllocRegisterExp = + ur::level_zero::urUSMHostAllocRegisterExp; pDdiTable->pfnImportExp = ur::level_zero::urUSMImportExp; pDdiTable->pfnReleaseExp = ur::level_zero::urUSMReleaseExp; diff --git a/unified-runtime/source/adapters/level_zero/ur_interface_loader.hpp b/unified-runtime/source/adapters/level_zero/ur_interface_loader.hpp index 7cb148e1c51bb..40449cfafc1b1 100644 --- a/unified-runtime/source/adapters/level_zero/ur_interface_loader.hpp +++ b/unified-runtime/source/adapters/level_zero/ur_interface_loader.hpp @@ -811,6 +811,11 @@ ur_result_t urProgramLinkExp(ur_context_handle_t hContext, uint32_t numDevices, ur_program_handle_t *phProgram); ur_result_t urUSMContextMemcpyExp(ur_context_handle_t hContext, void *pDst, const void *pSrc, size_t size); +ur_result_t urUSMHostAllocRegisterExp( + ur_context_handle_t hContext, void *pHostMem, size_t size, + const ur_exp_usm_host_alloc_register_properties_t *pProperties); +ur_result_t urUSMHostAllocUnregisterExp(ur_context_handle_t hContext, + void *pHostMem); ur_result_t urUSMImportExp(ur_context_handle_t hContext, void *pMem, size_t size); ur_result_t urUSMReleaseExp(ur_context_handle_t hContext, void *pMem); diff --git a/unified-runtime/source/adapters/mock/ur_mockddi.cpp b/unified-runtime/source/adapters/mock/ur_mockddi.cpp index 4a6a8c50f4467..61c70c42313b7 100644 --- a/unified-runtime/source/adapters/mock/ur_mockddi.cpp +++ b/unified-runtime/source/adapters/mock/ur_mockddi.cpp @@ -11951,6 +11951,100 @@ __urdlllocal ur_result_t UR_APICALL urUSMContextMemcpyExp( return exceptionToResult(std::current_exception()); } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUSMHostAllocRegisterExp +__urdlllocal ur_result_t UR_APICALL urUSMHostAllocRegisterExp( + /// [in] Handle of the context. + ur_context_handle_t hContext, + /// [in] Pointer to the host memory range to register. + void *pHostMem, + /// [in] Size in bytes of the host memory range to register, must be + /// page-aligned. + size_t size, + /// [in][optional] Pointer to host memory registration properties. + const ur_exp_usm_host_alloc_register_properties_t *pProperties) try { + ur_result_t result = UR_RESULT_SUCCESS; + + ur_usm_host_alloc_register_exp_params_t params = {&hContext, &pHostMem, &size, + &pProperties}; + + auto beforeCallback = reinterpret_cast( + mock::getCallbacks().get_before_callback("urUSMHostAllocRegisterExp")); + if (beforeCallback) { + result = beforeCallback(¶ms); + if (result != UR_RESULT_SUCCESS) { + return result; + } + } + + auto replaceCallback = reinterpret_cast( + mock::getCallbacks().get_replace_callback("urUSMHostAllocRegisterExp")); + if (replaceCallback) { + result = replaceCallback(¶ms); + } else { + + result = UR_RESULT_SUCCESS; + } + + if (result != UR_RESULT_SUCCESS) { + return result; + } + + auto afterCallback = reinterpret_cast( + mock::getCallbacks().get_after_callback("urUSMHostAllocRegisterExp")); + if (afterCallback) { + return afterCallback(¶ms); + } + + return result; +} catch (...) { + return exceptionToResult(std::current_exception()); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUSMHostAllocUnregisterExp +__urdlllocal ur_result_t UR_APICALL urUSMHostAllocUnregisterExp( + /// [in] Handle of the context. + ur_context_handle_t hContext, + /// [in][release] Pointer to the registered host memory range. + void *pHostMem) try { + ur_result_t result = UR_RESULT_SUCCESS; + + ur_usm_host_alloc_unregister_exp_params_t params = {&hContext, &pHostMem}; + + auto beforeCallback = reinterpret_cast( + mock::getCallbacks().get_before_callback("urUSMHostAllocUnregisterExp")); + if (beforeCallback) { + result = beforeCallback(¶ms); + if (result != UR_RESULT_SUCCESS) { + return result; + } + } + + auto replaceCallback = reinterpret_cast( + mock::getCallbacks().get_replace_callback("urUSMHostAllocUnregisterExp")); + if (replaceCallback) { + result = replaceCallback(¶ms); + } else { + + result = UR_RESULT_SUCCESS; + } + + if (result != UR_RESULT_SUCCESS) { + return result; + } + + auto afterCallback = reinterpret_cast( + mock::getCallbacks().get_after_callback("urUSMHostAllocUnregisterExp")); + if (afterCallback) { + return afterCallback(¶ms); + } + + return result; +} catch (...) { + return exceptionToResult(std::current_exception()); +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Intercept function for urUSMImportExp __urdlllocal ur_result_t UR_APICALL urUSMImportExp( @@ -14016,6 +14110,10 @@ UR_DLLEXPORT ur_result_t UR_APICALL urGetUSMExpProcAddrTable( pDdiTable->pfnContextMemcpyExp = driver::urUSMContextMemcpyExp; + pDdiTable->pfnHostAllocUnregisterExp = driver::urUSMHostAllocUnregisterExp; + + pDdiTable->pfnHostAllocRegisterExp = driver::urUSMHostAllocRegisterExp; + pDdiTable->pfnImportExp = driver::urUSMImportExp; pDdiTable->pfnReleaseExp = driver::urUSMReleaseExp; diff --git a/unified-runtime/source/common/stype_map_helpers.def b/unified-runtime/source/common/stype_map_helpers.def index ead220365d1bd..69088cb017aa1 100644 --- a/unified-runtime/source/common/stype_map_helpers.def +++ b/unified-runtime/source/common/stype_map_helpers.def @@ -183,3 +183,7 @@ struct stype_map template <> struct stype_map : stype_map_impl {}; +template <> +struct stype_map + : stype_map_impl { +}; diff --git a/unified-runtime/source/loader/layers/tracing/ur_trcddi.cpp b/unified-runtime/source/loader/layers/tracing/ur_trcddi.cpp index 283edbe0884c3..727905d9889d7 100644 --- a/unified-runtime/source/loader/layers/tracing/ur_trcddi.cpp +++ b/unified-runtime/source/loader/layers/tracing/ur_trcddi.cpp @@ -10121,6 +10121,89 @@ __urdlllocal ur_result_t UR_APICALL urUSMContextMemcpyExp( return result; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUSMHostAllocRegisterExp +__urdlllocal ur_result_t UR_APICALL urUSMHostAllocRegisterExp( + /// [in] Handle of the context. + ur_context_handle_t hContext, + /// [in] Pointer to the host memory range to register. + void *pHostMem, + /// [in] Size in bytes of the host memory range to register, must be + /// page-aligned. + size_t size, + /// [in][optional] Pointer to host memory registration properties. + const ur_exp_usm_host_alloc_register_properties_t *pProperties) { + auto pfnHostAllocRegisterExp = + getContext()->urDdiTable.USMExp.pfnHostAllocRegisterExp; + + if (nullptr == pfnHostAllocRegisterExp) + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + + ur_usm_host_alloc_register_exp_params_t params = {&hContext, &pHostMem, &size, + &pProperties}; + uint64_t instance = + getContext()->notify_begin(UR_FUNCTION_USM_HOST_ALLOC_REGISTER_EXP, + "urUSMHostAllocRegisterExp", ¶ms); + + auto &logger = getContext()->logger; + UR_LOG_L(logger, INFO, " ---> urUSMHostAllocRegisterExp\n"); + + ur_result_t result = + pfnHostAllocRegisterExp(hContext, pHostMem, size, pProperties); + + getContext()->notify_end(UR_FUNCTION_USM_HOST_ALLOC_REGISTER_EXP, + "urUSMHostAllocRegisterExp", ¶ms, &result, + instance); + + if (logger.getLevel() <= UR_LOGGER_LEVEL_INFO) { + std::ostringstream args_str; + ur::extras::printFunctionParams( + args_str, UR_FUNCTION_USM_HOST_ALLOC_REGISTER_EXP, ¶ms); + UR_LOG_L(logger, INFO, " <--- urUSMHostAllocRegisterExp({}) -> {};\n", + args_str.str(), result); + } + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUSMHostAllocUnregisterExp +__urdlllocal ur_result_t UR_APICALL urUSMHostAllocUnregisterExp( + /// [in] Handle of the context. + ur_context_handle_t hContext, + /// [in][release] Pointer to the registered host memory range. + void *pHostMem) { + auto pfnHostAllocUnregisterExp = + getContext()->urDdiTable.USMExp.pfnHostAllocUnregisterExp; + + if (nullptr == pfnHostAllocUnregisterExp) + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + + ur_usm_host_alloc_unregister_exp_params_t params = {&hContext, &pHostMem}; + uint64_t instance = + getContext()->notify_begin(UR_FUNCTION_USM_HOST_ALLOC_UNREGISTER_EXP, + "urUSMHostAllocUnregisterExp", ¶ms); + + auto &logger = getContext()->logger; + UR_LOG_L(logger, INFO, " ---> urUSMHostAllocUnregisterExp\n"); + + ur_result_t result = pfnHostAllocUnregisterExp(hContext, pHostMem); + + getContext()->notify_end(UR_FUNCTION_USM_HOST_ALLOC_UNREGISTER_EXP, + "urUSMHostAllocUnregisterExp", ¶ms, &result, + instance); + + if (logger.getLevel() <= UR_LOGGER_LEVEL_INFO) { + std::ostringstream args_str; + ur::extras::printFunctionParams( + args_str, UR_FUNCTION_USM_HOST_ALLOC_UNREGISTER_EXP, ¶ms); + UR_LOG_L(logger, INFO, " <--- urUSMHostAllocUnregisterExp({}) -> {};\n", + args_str.str(), result); + } + + return result; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Intercept function for urUSMImportExp __urdlllocal ur_result_t UR_APICALL urUSMImportExp( @@ -12319,6 +12402,14 @@ __urdlllocal ur_result_t UR_APICALL urGetUSMExpProcAddrTable( dditable.pfnContextMemcpyExp = pDdiTable->pfnContextMemcpyExp; pDdiTable->pfnContextMemcpyExp = ur_tracing_layer::urUSMContextMemcpyExp; + dditable.pfnHostAllocUnregisterExp = pDdiTable->pfnHostAllocUnregisterExp; + pDdiTable->pfnHostAllocUnregisterExp = + ur_tracing_layer::urUSMHostAllocUnregisterExp; + + dditable.pfnHostAllocRegisterExp = pDdiTable->pfnHostAllocRegisterExp; + pDdiTable->pfnHostAllocRegisterExp = + ur_tracing_layer::urUSMHostAllocRegisterExp; + dditable.pfnImportExp = pDdiTable->pfnImportExp; pDdiTable->pfnImportExp = ur_tracing_layer::urUSMImportExp; diff --git a/unified-runtime/source/loader/layers/validation/ur_valddi.cpp b/unified-runtime/source/loader/layers/validation/ur_valddi.cpp index 569545718f69e..9e869a5fd781c 100644 --- a/unified-runtime/source/loader/layers/validation/ur_valddi.cpp +++ b/unified-runtime/source/loader/layers/validation/ur_valddi.cpp @@ -10893,6 +10893,83 @@ __urdlllocal ur_result_t UR_APICALL urUSMContextMemcpyExp( return result; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUSMHostAllocRegisterExp +__urdlllocal ur_result_t UR_APICALL urUSMHostAllocRegisterExp( + /// [in] Handle of the context. + ur_context_handle_t hContext, + /// [in] Pointer to the host memory range to register. + void *pHostMem, + /// [in] Size in bytes of the host memory range to register, must be + /// page-aligned. + size_t size, + /// [in][optional] Pointer to host memory registration properties. + const ur_exp_usm_host_alloc_register_properties_t *pProperties) { + auto pfnHostAllocRegisterExp = + getContext()->urDdiTable.USMExp.pfnHostAllocRegisterExp; + + if (nullptr == pfnHostAllocRegisterExp) { + return UR_RESULT_ERROR_UNINITIALIZED; + } + + if (getContext()->enableParameterValidation) { + if (NULL == pHostMem) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if (NULL == hContext) + return UR_RESULT_ERROR_INVALID_NULL_HANDLE; + + if (NULL != pProperties && + UR_EXP_USM_HOST_ALLOC_REGISTER_FLAGS_MASK & pProperties->flags) + return UR_RESULT_ERROR_INVALID_ENUMERATION; + + if (size == 0) + return UR_RESULT_ERROR_INVALID_VALUE; + } + + if (getContext()->enableLifetimeValidation && + !getContext()->refCountContext->isReferenceValid(hContext)) { + URLOG_CTX_INVALID_REFERENCE(hContext); + } + + ur_result_t result = + pfnHostAllocRegisterExp(hContext, pHostMem, size, pProperties); + + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUSMHostAllocUnregisterExp +__urdlllocal ur_result_t UR_APICALL urUSMHostAllocUnregisterExp( + /// [in] Handle of the context. + ur_context_handle_t hContext, + /// [in][release] Pointer to the registered host memory range. + void *pHostMem) { + auto pfnHostAllocUnregisterExp = + getContext()->urDdiTable.USMExp.pfnHostAllocUnregisterExp; + + if (nullptr == pfnHostAllocUnregisterExp) { + return UR_RESULT_ERROR_UNINITIALIZED; + } + + if (getContext()->enableParameterValidation) { + if (NULL == pHostMem) + return UR_RESULT_ERROR_INVALID_NULL_POINTER; + + if (NULL == hContext) + return UR_RESULT_ERROR_INVALID_NULL_HANDLE; + } + + if (getContext()->enableLifetimeValidation && + !getContext()->refCountContext->isReferenceValid(hContext)) { + URLOG_CTX_INVALID_REFERENCE(hContext); + } + + ur_result_t result = pfnHostAllocUnregisterExp(hContext, pHostMem); + + return result; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Intercept function for urUSMImportExp __urdlllocal ur_result_t UR_APICALL urUSMImportExp( @@ -13106,6 +13183,14 @@ UR_DLLEXPORT ur_result_t UR_APICALL urGetUSMExpProcAddrTable( dditable.pfnContextMemcpyExp = pDdiTable->pfnContextMemcpyExp; pDdiTable->pfnContextMemcpyExp = ur_validation_layer::urUSMContextMemcpyExp; + dditable.pfnHostAllocUnregisterExp = pDdiTable->pfnHostAllocUnregisterExp; + pDdiTable->pfnHostAllocUnregisterExp = + ur_validation_layer::urUSMHostAllocUnregisterExp; + + dditable.pfnHostAllocRegisterExp = pDdiTable->pfnHostAllocRegisterExp; + pDdiTable->pfnHostAllocRegisterExp = + ur_validation_layer::urUSMHostAllocRegisterExp; + dditable.pfnImportExp = pDdiTable->pfnImportExp; pDdiTable->pfnImportExp = ur_validation_layer::urUSMImportExp; diff --git a/unified-runtime/source/loader/loader.def.in b/unified-runtime/source/loader/loader.def.in index d4a566678b117..c4618f3e8a342 100644 --- a/unified-runtime/source/loader/loader.def.in +++ b/unified-runtime/source/loader/loader.def.in @@ -382,6 +382,8 @@ EXPORTS urPrintExpSamplerCubemapFilterMode urPrintExpSamplerCubemapProperties urPrintExpSamplerMipProperties + urPrintExpUsmHostAllocRegisterFlags + urPrintExpUsmHostAllocRegisterProperties urPrintExpWin32Handle urPrintFunction urPrintFunctionParams @@ -552,6 +554,8 @@ EXPORTS urPrintUsmFreeParams urPrintUsmGetMemAllocInfoParams urPrintUsmHostAllocParams + urPrintUsmHostAllocRegisterExpParams + urPrintUsmHostAllocUnregisterExpParams urPrintUsmHostDesc urPrintUsmHostMemFlags urPrintUsmImportExpParams @@ -631,6 +635,8 @@ EXPORTS urUSMFree urUSMGetMemAllocInfo urUSMHostAlloc + urUSMHostAllocRegisterExp + urUSMHostAllocUnregisterExp urUSMImportExp urUSMPitchedAllocExp urUSMPoolCreate diff --git a/unified-runtime/source/loader/loader.map.in b/unified-runtime/source/loader/loader.map.in index 1606100424c00..20641bb912140 100644 --- a/unified-runtime/source/loader/loader.map.in +++ b/unified-runtime/source/loader/loader.map.in @@ -382,6 +382,8 @@ urPrintExpSamplerCubemapFilterMode; urPrintExpSamplerCubemapProperties; urPrintExpSamplerMipProperties; + urPrintExpUsmHostAllocRegisterFlags; + urPrintExpUsmHostAllocRegisterProperties; urPrintExpWin32Handle; urPrintFunction; urPrintFunctionParams; @@ -552,6 +554,8 @@ urPrintUsmFreeParams; urPrintUsmGetMemAllocInfoParams; urPrintUsmHostAllocParams; + urPrintUsmHostAllocRegisterExpParams; + urPrintUsmHostAllocUnregisterExpParams; urPrintUsmHostDesc; urPrintUsmHostMemFlags; urPrintUsmImportExpParams; @@ -631,6 +635,8 @@ urUSMFree; urUSMGetMemAllocInfo; urUSMHostAlloc; + urUSMHostAllocRegisterExp; + urUSMHostAllocUnregisterExp; urUSMImportExp; urUSMPitchedAllocExp; urUSMPoolCreate; diff --git a/unified-runtime/source/loader/ur_ldrddi.cpp b/unified-runtime/source/loader/ur_ldrddi.cpp index 090193594d687..a3c41b6abff68 100644 --- a/unified-runtime/source/loader/ur_ldrddi.cpp +++ b/unified-runtime/source/loader/ur_ldrddi.cpp @@ -5757,6 +5757,47 @@ __urdlllocal ur_result_t UR_APICALL urUSMContextMemcpyExp( return pfnContextMemcpyExp(hContext, pDst, pSrc, size); } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUSMHostAllocRegisterExp +__urdlllocal ur_result_t UR_APICALL urUSMHostAllocRegisterExp( + /// [in] Handle of the context. + ur_context_handle_t hContext, + /// [in] Pointer to the host memory range to register. + void *pHostMem, + /// [in] Size in bytes of the host memory range to register, must be + /// page-aligned. + size_t size, + /// [in][optional] Pointer to host memory registration properties. + const ur_exp_usm_host_alloc_register_properties_t *pProperties) { + + auto *dditable = *reinterpret_cast(hContext); + + auto *pfnHostAllocRegisterExp = dditable->USMExp.pfnHostAllocRegisterExp; + if (nullptr == pfnHostAllocRegisterExp) + return UR_RESULT_ERROR_UNINITIALIZED; + + // forward to device-platform + return pfnHostAllocRegisterExp(hContext, pHostMem, size, pProperties); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Intercept function for urUSMHostAllocUnregisterExp +__urdlllocal ur_result_t UR_APICALL urUSMHostAllocUnregisterExp( + /// [in] Handle of the context. + ur_context_handle_t hContext, + /// [in][release] Pointer to the registered host memory range. + void *pHostMem) { + + auto *dditable = *reinterpret_cast(hContext); + + auto *pfnHostAllocUnregisterExp = dditable->USMExp.pfnHostAllocUnregisterExp; + if (nullptr == pfnHostAllocUnregisterExp) + return UR_RESULT_ERROR_UNINITIALIZED; + + // forward to device-platform + return pfnHostAllocUnregisterExp(hContext, pHostMem); +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Intercept function for urUSMImportExp __urdlllocal ur_result_t UR_APICALL urUSMImportExp( @@ -7612,6 +7653,9 @@ UR_DLLEXPORT ur_result_t UR_APICALL urGetUSMExpProcAddrTable( pDdiTable->pfnPoolTrimToExp = ur_loader::urUSMPoolTrimToExp; pDdiTable->pfnPitchedAllocExp = ur_loader::urUSMPitchedAllocExp; pDdiTable->pfnContextMemcpyExp = ur_loader::urUSMContextMemcpyExp; + pDdiTable->pfnHostAllocUnregisterExp = + ur_loader::urUSMHostAllocUnregisterExp; + pDdiTable->pfnHostAllocRegisterExp = ur_loader::urUSMHostAllocRegisterExp; pDdiTable->pfnImportExp = ur_loader::urUSMImportExp; pDdiTable->pfnReleaseExp = ur_loader::urUSMReleaseExp; } else { diff --git a/unified-runtime/source/loader/ur_libapi.cpp b/unified-runtime/source/loader/ur_libapi.cpp index f93dd94ff4dba..a96df6bbf079a 100644 --- a/unified-runtime/source/loader/ur_libapi.cpp +++ b/unified-runtime/source/loader/ur_libapi.cpp @@ -10570,6 +10570,74 @@ ur_result_t UR_APICALL urUSMContextMemcpyExp( return exceptionToResult(std::current_exception()); } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Maps a host memory range to make it recognizable by the underlying +/// adapter. The host memory must remain valid throughout the +/// registration lifetime. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pHostMem` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `NULL != pProperties && +/// ::UR_EXP_USM_HOST_ALLOC_REGISTER_FLAGS_MASK & pProperties->flags` +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// + `size == 0` +ur_result_t UR_APICALL urUSMHostAllocRegisterExp( + /// [in] Handle of the context. + ur_context_handle_t hContext, + /// [in] Pointer to the host memory range to register. + void *pHostMem, + /// [in] Size in bytes of the host memory range to register, must be + /// page-aligned. + size_t size, + /// [in][optional] Pointer to host memory registration properties. + const ur_exp_usm_host_alloc_register_properties_t *pProperties) try { + auto pfnHostAllocRegisterExp = + ur_lib::getContext()->urDdiTable.USMExp.pfnHostAllocRegisterExp; + if (nullptr == pfnHostAllocRegisterExp) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnHostAllocRegisterExp(hContext, pHostMem, size, pProperties); +} catch (...) { + return exceptionToResult(std::current_exception()); +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Unregister a previously registered host memory range. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pHostMem` +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// + Invalid host memory range. +ur_result_t UR_APICALL urUSMHostAllocUnregisterExp( + /// [in] Handle of the context. + ur_context_handle_t hContext, + /// [in][release] Pointer to the registered host memory range. + void *pHostMem) try { + auto pfnHostAllocUnregisterExp = + ur_lib::getContext()->urDdiTable.USMExp.pfnHostAllocUnregisterExp; + if (nullptr == pfnHostAllocUnregisterExp) + return UR_RESULT_ERROR_UNINITIALIZED; + + return pfnHostAllocUnregisterExp(hContext, pHostMem); +} catch (...) { + return exceptionToResult(std::current_exception()); +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Import memory into USM /// diff --git a/unified-runtime/source/loader/ur_print.cpp b/unified-runtime/source/loader/ur_print.cpp index 6d20fcdd33669..dd2c3ef7f42c5 100644 --- a/unified-runtime/source/loader/ur_print.cpp +++ b/unified-runtime/source/loader/ur_print.cpp @@ -1162,6 +1162,22 @@ ur_result_t urPrintExpProgramFlags(enum ur_exp_program_flag_t value, return str_copy(&ss, buffer, buff_size, out_size); } +ur_result_t urPrintExpUsmHostAllocRegisterFlags( + enum ur_exp_usm_host_alloc_register_flag_t value, char *buffer, + const size_t buff_size, size_t *out_size) { + std::stringstream ss; + ss << value; + return str_copy(&ss, buffer, buff_size, out_size); +} + +ur_result_t urPrintExpUsmHostAllocRegisterProperties( + const struct ur_exp_usm_host_alloc_register_properties_t params, + char *buffer, const size_t buff_size, size_t *out_size) { + std::stringstream ss; + ss << params; + return str_copy(&ss, buffer, buff_size, out_size); +} + ur_result_t urPrintExpPeerInfo(enum ur_exp_peer_info_t value, char *buffer, const size_t buff_size, size_t *out_size) { std::stringstream ss; @@ -3048,6 +3064,22 @@ ur_result_t urPrintUsmContextMemcpyExpParams( return str_copy(&ss, buffer, buff_size, out_size); } +ur_result_t urPrintUsmHostAllocUnregisterExpParams( + const struct ur_usm_host_alloc_unregister_exp_params_t *params, + char *buffer, const size_t buff_size, size_t *out_size) { + std::stringstream ss; + ss << params; + return str_copy(&ss, buffer, buff_size, out_size); +} + +ur_result_t urPrintUsmHostAllocRegisterExpParams( + const struct ur_usm_host_alloc_register_exp_params_t *params, char *buffer, + const size_t buff_size, size_t *out_size) { + std::stringstream ss; + ss << params; + return str_copy(&ss, buffer, buff_size, out_size); +} + ur_result_t urPrintUsmImportExpParams(const struct ur_usm_import_exp_params_t *params, char *buffer, const size_t buff_size, diff --git a/unified-runtime/source/ur_api.cpp b/unified-runtime/source/ur_api.cpp index d4c8260affdc5..1deb3faf35850 100644 --- a/unified-runtime/source/ur_api.cpp +++ b/unified-runtime/source/ur_api.cpp @@ -9193,6 +9193,62 @@ ur_result_t UR_APICALL urUSMContextMemcpyExp( return result; } +/////////////////////////////////////////////////////////////////////////////// +/// @brief Maps a host memory range to make it recognizable by the underlying +/// adapter. The host memory must remain valid throughout the +/// registration lifetime. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pHostMem` +/// - ::UR_RESULT_ERROR_INVALID_ENUMERATION +/// + `NULL != pProperties && +/// ::UR_EXP_USM_HOST_ALLOC_REGISTER_FLAGS_MASK & pProperties->flags` +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// + `size == 0` +ur_result_t UR_APICALL urUSMHostAllocRegisterExp( + /// [in] Handle of the context. + ur_context_handle_t hContext, + /// [in] Pointer to the host memory range to register. + void *pHostMem, + /// [in] Size in bytes of the host memory range to register, must be + /// page-aligned. + size_t size, + /// [in][optional] Pointer to host memory registration properties. + const ur_exp_usm_host_alloc_register_properties_t *pProperties) { + ur_result_t result = UR_RESULT_SUCCESS; + return result; +} + +/////////////////////////////////////////////////////////////////////////////// +/// @brief Unregister a previously registered host memory range. +/// +/// @returns +/// - ::UR_RESULT_SUCCESS +/// - ::UR_RESULT_ERROR_UNINITIALIZED +/// - ::UR_RESULT_ERROR_DEVICE_LOST +/// - ::UR_RESULT_ERROR_ADAPTER_SPECIFIC +/// - ::UR_RESULT_ERROR_INVALID_NULL_HANDLE +/// + `NULL == hContext` +/// - ::UR_RESULT_ERROR_INVALID_NULL_POINTER +/// + `NULL == pHostMem` +/// - ::UR_RESULT_ERROR_INVALID_VALUE +/// + Invalid host memory range. +ur_result_t UR_APICALL urUSMHostAllocUnregisterExp( + /// [in] Handle of the context. + ur_context_handle_t hContext, + /// [in][release] Pointer to the registered host memory range. + void *pHostMem) { + ur_result_t result = UR_RESULT_SUCCESS; + return result; +} + /////////////////////////////////////////////////////////////////////////////// /// @brief Import memory into USM /// diff --git a/unified-runtime/tools/urinfo/urinfo.hpp b/unified-runtime/tools/urinfo/urinfo.hpp index a58277530c210..7ebf5401f1ac6 100644 --- a/unified-runtime/tools/urinfo/urinfo.hpp +++ b/unified-runtime/tools/urinfo/urinfo.hpp @@ -463,6 +463,9 @@ inline void printDeviceInfos(ur_device_handle_t hDevice, printDeviceInfo( hDevice, UR_DEVICE_INFO_GRAPH_RECORD_AND_REPLAY_SUPPORT_EXP); std::cout << prefix; + printDeviceInfo( + hDevice, UR_DEVICE_INFO_USM_HOST_ALLOC_REGISTER_SUPPORT_EXP); + std::cout << prefix; printDeviceInfo(hDevice, UR_DEVICE_INFO_USM_P2P_SUPPORT_EXP); std::cout << prefix; printDeviceInfo(hDevice, From 19f7ce0f072c87e08ec29369e06f07f4eea15d32 Mon Sep 17 00:00:00 2001 From: Krzysztof Swiecicki Date: Wed, 14 Jan 2026 14:24:20 +0000 Subject: [PATCH 2/4] Add function stubs --- unified-runtime/source/adapters/cuda/usm.cpp | 11 +++++++++++ unified-runtime/source/adapters/hip/usm.cpp | 11 +++++++++++ unified-runtime/source/adapters/level_zero/usm.cpp | 12 ++++++++++++ .../source/adapters/level_zero/v2/usm.cpp | 11 +++++++++++ unified-runtime/source/adapters/native_cpu/usm.cpp | 11 +++++++++++ unified-runtime/source/adapters/offload/usm.cpp | 11 +++++++++++ unified-runtime/source/adapters/opencl/usm.cpp | 11 +++++++++++ 7 files changed, 78 insertions(+) diff --git a/unified-runtime/source/adapters/cuda/usm.cpp b/unified-runtime/source/adapters/cuda/usm.cpp index c805c1084ec0f..5def2c9cc54ce 100644 --- a/unified-runtime/source/adapters/cuda/usm.cpp +++ b/unified-runtime/source/adapters/cuda/usm.cpp @@ -581,3 +581,14 @@ UR_APIEXPORT ur_result_t UR_APICALL urUSMContextMemcpyExp(ur_context_handle_t, UR_CHECK_ERROR(cuMemcpy((CUdeviceptr)pDst, (CUdeviceptr)pSrc, Size)); return UR_RESULT_SUCCESS; } + +UR_APIEXPORT ur_result_t UR_APICALL urUSMHostAllocRegisterExp( + ur_context_handle_t /*hContext*/, void * /*pHostMem*/, size_t /*size*/, + const ur_exp_usm_host_alloc_register_properties_t * /*pProperties*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +UR_APIEXPORT ur_result_t UR_APICALL urUSMHostAllocUnregisterExp( + ur_context_handle_t /*hContext*/, void * /*pHostMem*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} diff --git a/unified-runtime/source/adapters/hip/usm.cpp b/unified-runtime/source/adapters/hip/usm.cpp index aa2b945c3fc7f..84bb2fb0bb807 100644 --- a/unified-runtime/source/adapters/hip/usm.cpp +++ b/unified-runtime/source/adapters/hip/usm.cpp @@ -541,3 +541,14 @@ UR_APIEXPORT ur_result_t UR_APICALL urUSMContextMemcpyExp(ur_context_handle_t, size_t) { return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; } + +UR_APIEXPORT ur_result_t UR_APICALL urUSMHostAllocRegisterExp( + ur_context_handle_t /*hContext*/, void * /*pHostMem*/, size_t /*size*/, + const ur_exp_usm_host_alloc_register_properties_t * /*pProperties*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +UR_APIEXPORT ur_result_t UR_APICALL urUSMHostAllocUnregisterExp( + ur_context_handle_t /*hContext*/, void * /*pHostMem*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} diff --git a/unified-runtime/source/adapters/level_zero/usm.cpp b/unified-runtime/source/adapters/level_zero/usm.cpp index 5a5dab0e527c7..48f1a8e93bd78 100644 --- a/unified-runtime/source/adapters/level_zero/usm.cpp +++ b/unified-runtime/source/adapters/level_zero/usm.cpp @@ -707,6 +707,18 @@ ur_result_t UR_APICALL urUSMContextMemcpyExp(ur_context_handle_t Context, pSrc, Size, nullptr, 0, nullptr)); return UR_RESULT_SUCCESS; } + +ur_result_t UR_APICALL urUSMHostAllocRegisterExp( + ur_context_handle_t /*hContext*/, void * /*pHostMem*/, size_t /*size*/, + const ur_exp_usm_host_alloc_register_properties_t * /*pProperties*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ur_result_t UR_APICALL urUSMHostAllocUnregisterExp( + ur_context_handle_t /*hContext*/, void * /*pHostMem*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + } // namespace ur::level_zero static ur_result_t USMFreeImpl(ur_context_handle_t Context, void *Ptr) { diff --git a/unified-runtime/source/adapters/level_zero/v2/usm.cpp b/unified-runtime/source/adapters/level_zero/v2/usm.cpp index 5042697894386..c52b1f3720715 100644 --- a/unified-runtime/source/adapters/level_zero/v2/usm.cpp +++ b/unified-runtime/source/adapters/level_zero/v2/usm.cpp @@ -852,4 +852,15 @@ ur_result_t UR_APICALL urUSMContextMemcpyExp(ur_context_handle_t hContext, return UR_RESULT_SUCCESS; } +ur_result_t urUSMHostAllocRegisterExp( + ur_context_handle_t /*hContext*/, void * /*pHostMem*/, size_t /*size*/, + const ur_exp_usm_host_alloc_register_properties_t * /*pProperties*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +ur_result_t urUSMHostAllocUnregisterExp(ur_context_handle_t /*hContext*/, + void * /*pHostMem*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + } // namespace ur::level_zero diff --git a/unified-runtime/source/adapters/native_cpu/usm.cpp b/unified-runtime/source/adapters/native_cpu/usm.cpp index c404e910c76ef..37d0c40d40d4f 100644 --- a/unified-runtime/source/adapters/native_cpu/usm.cpp +++ b/unified-runtime/source/adapters/native_cpu/usm.cpp @@ -188,3 +188,14 @@ UR_APIEXPORT ur_result_t UR_APICALL urUSMContextMemcpyExp(ur_context_handle_t, size_t) { DIE_NO_IMPLEMENTATION; } + +UR_APIEXPORT ur_result_t UR_APICALL urUSMHostAllocRegisterExp( + ur_context_handle_t /*hContext*/, void * /*pHostMem*/, size_t /*size*/, + const ur_exp_usm_host_alloc_register_properties_t * /*pProperties*/) { + DIE_NO_IMPLEMENTATION; +} + +UR_APIEXPORT ur_result_t UR_APICALL urUSMHostAllocUnregisterExp( + ur_context_handle_t /*hContext*/, void * /*pHostMem*/) { + DIE_NO_IMPLEMENTATION; +} diff --git a/unified-runtime/source/adapters/offload/usm.cpp b/unified-runtime/source/adapters/offload/usm.cpp index e457c59896d53..63bf8ec58e2d8 100644 --- a/unified-runtime/source/adapters/offload/usm.cpp +++ b/unified-runtime/source/adapters/offload/usm.cpp @@ -64,3 +64,14 @@ UR_APIEXPORT ur_result_t UR_APICALL urUSMGetMemAllocInfo( [[maybe_unused]] size_t *pPropSizeRet) { return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; } + +UR_APIEXPORT ur_result_t UR_APICALL urUSMHostAllocRegisterExp( + ur_context_handle_t /*hContext*/, void * /*pHostMem*/, size_t /*size*/, + const ur_exp_usm_host_alloc_register_properties_t * /*pProperties*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +UR_APIEXPORT ur_result_t UR_APICALL urUSMHostAllocUnregisterExp( + ur_context_handle_t /*hContext*/, void * /*pHostMem*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} diff --git a/unified-runtime/source/adapters/opencl/usm.cpp b/unified-runtime/source/adapters/opencl/usm.cpp index 09cf31aee8645..e4894e3ff1fa3 100644 --- a/unified-runtime/source/adapters/opencl/usm.cpp +++ b/unified-runtime/source/adapters/opencl/usm.cpp @@ -830,3 +830,14 @@ UR_APIEXPORT ur_result_t UR_APICALL urUSMContextMemcpyExp(ur_context_handle_t, size_t) { return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; } + +UR_APIEXPORT ur_result_t UR_APICALL urUSMHostAllocRegisterExp( + ur_context_handle_t /*hContext*/, void * /*pHostMem*/, size_t /*size*/, + const ur_exp_usm_host_alloc_register_properties_t * /*pProperties*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} + +UR_APIEXPORT ur_result_t UR_APICALL urUSMHostAllocUnregisterExp( + ur_context_handle_t /*hContext*/, void * /*pHostMem*/) { + return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +} From 6db26852c3df34949fd48703ed052b9bad7fd216 Mon Sep 17 00:00:00 2001 From: Krzysztof Swiecicki Date: Wed, 14 Jan 2026 15:43:51 +0000 Subject: [PATCH 3/4] [UR][L0v2] Implement exp-usm-host-alloc-register.yml spec --- .../source/adapters/level_zero/v2/usm.cpp | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/unified-runtime/source/adapters/level_zero/v2/usm.cpp b/unified-runtime/source/adapters/level_zero/v2/usm.cpp index c52b1f3720715..64c06af354059 100644 --- a/unified-runtime/source/adapters/level_zero/v2/usm.cpp +++ b/unified-runtime/source/adapters/level_zero/v2/usm.cpp @@ -349,7 +349,6 @@ ur_usm_pool_handle_t_::allocateEnqueued(ur_context_handle_t hContext, if ((alignment & (alignment - 1)) != 0) { return std::nullopt; } - auto deviceFlags = getDeviceFlags(pUSMDesc); auto umfPool = getPool(usm::pool_descriptor{ @@ -853,14 +852,28 @@ ur_result_t UR_APICALL urUSMContextMemcpyExp(ur_context_handle_t hContext, } ur_result_t urUSMHostAllocRegisterExp( - ur_context_handle_t /*hContext*/, void * /*pHostMem*/, size_t /*size*/, + ur_context_handle_t hContext, void *pHostMem, size_t size, const ur_exp_usm_host_alloc_register_properties_t * /*pProperties*/) { - return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; + ze_external_memmap_sysmem_ext_desc_t sysMemDesc = { + ZE_STRUCTURE_TYPE_EXTERNAL_MEMMAP_SYSMEM_EXT_DESC, nullptr, pHostMem, + size}; + + ze_host_mem_alloc_desc_t hostDesc = {ZE_STRUCTURE_TYPE_HOST_MEM_ALLOC_DESC, + &sysMemDesc, 0}; + + void *mappedMem = nullptr; + ZE2UR_CALL(zeMemAllocHost, + (hContext->getZeHandle(), &hostDesc, size, 1, &mappedMem)); + assert(mappedMem == pHostMem); + + return UR_RESULT_SUCCESS; } -ur_result_t urUSMHostAllocUnregisterExp(ur_context_handle_t /*hContext*/, - void * /*pHostMem*/) { - return UR_RESULT_ERROR_UNSUPPORTED_FEATURE; +ur_result_t urUSMHostAllocUnregisterExp(ur_context_handle_t hContext, + void *pHostMem) { + ZE2UR_CALL(zeMemFree, (hContext->getZeHandle(), pHostMem)); + + return UR_RESULT_SUCCESS; } } // namespace ur::level_zero From cc877d1e4f0b7cf16de76741e60cf29b0e9f3e72 Mon Sep 17 00:00:00 2001 From: Krzysztof Swiecicki Date: Wed, 14 Jan 2026 15:44:14 +0000 Subject: [PATCH 4/4] Add tests --- .../test/conformance/CMakeLists.txt | 1 + .../exp_usm_host_mem_register/CMakeLists.txt | 7 ++ .../urUSMHostMemRegister.cpp | 76 +++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 unified-runtime/test/conformance/exp_usm_host_mem_register/CMakeLists.txt create mode 100644 unified-runtime/test/conformance/exp_usm_host_mem_register/urUSMHostMemRegister.cpp diff --git a/unified-runtime/test/conformance/CMakeLists.txt b/unified-runtime/test/conformance/CMakeLists.txt index 7d215f1b5ee14..ce86494a76a35 100644 --- a/unified-runtime/test/conformance/CMakeLists.txt +++ b/unified-runtime/test/conformance/CMakeLists.txt @@ -71,6 +71,7 @@ add_subdirectory(sampler) add_subdirectory(virtual_memory) add_subdirectory(exp_usm_context_memcpy) add_subdirectory(exp_graph) +add_subdirectory(exp_usm_host_mem_register) set(TEST_SUBDIRECTORIES_DPCXX "device_code" diff --git a/unified-runtime/test/conformance/exp_usm_host_mem_register/CMakeLists.txt b/unified-runtime/test/conformance/exp_usm_host_mem_register/CMakeLists.txt new file mode 100644 index 0000000000000..3b591002b77d4 --- /dev/null +++ b/unified-runtime/test/conformance/exp_usm_host_mem_register/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (C) 2026 Intel Corporation +# Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +# See LICENSE.TXT +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +add_conformance_devices_test(exp_usm_host_mem_register + urUSMHostMemRegister.cpp) diff --git a/unified-runtime/test/conformance/exp_usm_host_mem_register/urUSMHostMemRegister.cpp b/unified-runtime/test/conformance/exp_usm_host_mem_register/urUSMHostMemRegister.cpp new file mode 100644 index 0000000000000..5eb4774d37093 --- /dev/null +++ b/unified-runtime/test/conformance/exp_usm_host_mem_register/urUSMHostMemRegister.cpp @@ -0,0 +1,76 @@ +// Copyright (C) 2026 Intel Corporation +// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM +// Exceptions. See LICENSE.TXT +// +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "uur/fixtures.h" + +struct urUSMHostMemRegisterTest : uur::urQueueTest { + static constexpr size_t allocSize = (1 << 12); // 4KB + static constexpr uint8_t testValue = 0x77; + void *alloc = nullptr; + + void SetUp() override { + UUR_RETURN_ON_FATAL_FAILURE(urQueueTest::SetUp()); + + UUR_KNOWN_FAILURE_ON(uur::CUDA{}, uur::HIP{}, uur::NativeCPU{}, + uur::OpenCL{}, uur::LevelZero{}); + + alloc = aligned_alloc(allocSize, allocSize); + ASSERT_NE(alloc, nullptr); + } + + void TearDown() override { + if (alloc) { + free(alloc); + } + urQueueTest::TearDown(); + } + + void validateBuffer(const void *buffer, const size_t size, + const uint8_t expectedValue) { + const uint8_t *byteBuffer = static_cast(buffer); + for (size_t i = 0; i < size; ++i) { + ASSERT_EQ(byteBuffer[i], expectedValue) + << "Buffer mismatch at index " << i << ": expected " + << static_cast(expectedValue) << ", got " + << static_cast(byteBuffer[i]); + } + } +}; + +UUR_INSTANTIATE_DEVICE_TEST_SUITE(urUSMHostMemRegisterTest); + +TEST_P(urUSMHostMemRegisterTest, Success) { + ASSERT_SUCCESS(urUSMHostAllocRegisterExp(context, alloc, allocSize, nullptr)); + + void *alloc2 = nullptr; + ASSERT_SUCCESS(urUSMHostAlloc(context, nullptr, nullptr, allocSize, &alloc2)); + + memset(alloc, testValue, allocSize); + memset(alloc2, 0, allocSize); + + ASSERT_SUCCESS(urEnqueueUSMMemcpy(queue, true, alloc2, alloc, allocSize, 0, + nullptr, nullptr)); + + validateBuffer(alloc2, allocSize, testValue); + + ASSERT_SUCCESS(urUSMHostAllocUnregisterExp(context, alloc)); + ASSERT_SUCCESS(urUSMFree(context, alloc2)); +} + +TEST_P(urUSMHostMemRegisterTest, InvalidNullHandleContext) { + ASSERT_EQ(urUSMHostAllocRegisterExp(nullptr, alloc, allocSize, nullptr), + UR_RESULT_ERROR_INVALID_NULL_HANDLE); +} + +TEST_P(urUSMHostMemRegisterTest, InvalidValueAllocSize) { + ASSERT_EQ(urUSMHostAllocRegisterExp(context, alloc, 0, nullptr), + UR_RESULT_ERROR_INVALID_VALUE); +} + +TEST_P(urUSMHostMemRegisterTest, InvalidNullPointerHostMem) { + ASSERT_EQ(urUSMHostAllocRegisterExp(context, nullptr, allocSize, nullptr), + UR_RESULT_ERROR_INVALID_NULL_POINTER); +}