Files
compute-runtime/shared/source/os_interface/linux/ioctl_helper_prelim.cpp
Jitendra Sharma 322089fa5f feature: Pass cookie in vmBindExt
Provide cookie in vmBindExt, so that information about deviceBitField
could be provided to vmBind. This information could be used in
debugUMD code to to create grouping of ISA segments on different
tiles.

Related-To: NEO-11104
Signed-off-by: Jitendra Sharma <jitendra.sharma@intel.com>
2024-12-16 14:11:20 +01:00

1302 lines
51 KiB
C++

/*
* Copyright (C) 2021-2024 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/debug_settings/debug_settings_manager.h"
#include "shared/source/execution_environment/execution_environment.h"
#include "shared/source/execution_environment/root_device_environment.h"
#include "shared/source/helpers/basic_math.h"
#include "shared/source/helpers/bit_helpers.h"
#include "shared/source/helpers/common_types.h"
#include "shared/source/helpers/constants.h"
#include "shared/source/helpers/debug_helpers.h"
#include "shared/source/helpers/gfx_core_helper.h"
#include "shared/source/helpers/hw_info.h"
#include "shared/source/helpers/ptr_math.h"
#include "shared/source/helpers/string.h"
#include "shared/source/memory_manager/graphics_allocation.h"
#include "shared/source/os_interface/linux/cache_info.h"
#include "shared/source/os_interface/linux/drm_buffer_object.h"
#include "shared/source/os_interface/linux/drm_neo.h"
#include "shared/source/os_interface/linux/drm_wrappers.h"
#include "shared/source/os_interface/linux/engine_info.h"
#include "shared/source/os_interface/linux/i915_prelim.h"
#include "shared/source/os_interface/linux/ioctl_helper.h"
#include "shared/source/os_interface/linux/os_context_linux.h"
#include "shared/source/os_interface/linux/sys_calls.h"
#include "shared/source/os_interface/product_helper.h"
#include "shared/source/utilities/logger.h"
#include <algorithm>
#include <cerrno>
#include <cstring>
#include <fcntl.h>
#include <iostream>
#include <sys/ioctl.h>
namespace NEO {
IoctlHelperPrelim20::IoctlHelperPrelim20(Drm &drmArg) : IoctlHelperI915(drmArg) {
const auto &productHelper = this->drm.getRootDeviceEnvironment().getHelper<ProductHelper>();
handleExecBufferInNonBlockMode = productHelper.isNonBlockingGpuSubmissionSupported();
if (debugManager.flags.ForceNonblockingExecbufferCalls.get() != -1) {
handleExecBufferInNonBlockMode = debugManager.flags.ForceNonblockingExecbufferCalls.get();
}
if (handleExecBufferInNonBlockMode) {
auto fileDescriptor = this->drm.getFileDescriptor();
auto flags = SysCalls::fcntl(fileDescriptor, F_GETFL);
[[maybe_unused]] auto status = SysCalls::fcntl(fileDescriptor, F_SETFL, flags | O_NONBLOCK);
DEBUG_BREAK_IF(status != 0);
}
};
bool IoctlHelperPrelim20::isSetPairAvailable() {
int setPairSupported = 0;
GetParam getParam{};
getParam.param = PRELIM_I915_PARAM_HAS_SET_PAIR;
getParam.value = &setPairSupported;
int retVal = IoctlHelper::ioctl(DrmIoctl::getparam, &getParam);
if (retVal) {
return false;
}
return setPairSupported;
}
bool IoctlHelperPrelim20::isChunkingAvailable() {
int chunkSupported = 0;
GetParam getParam{};
getParam.param = PRELIM_I915_PARAM_HAS_CHUNK_SIZE;
getParam.value = &chunkSupported;
int retVal = IoctlHelper::ioctl(DrmIoctl::getparam, &getParam);
if (retVal) {
return false;
}
return chunkSupported;
}
bool IoctlHelperPrelim20::getTopologyDataAndMap(const HardwareInfo &hwInfo, DrmQueryTopologyData &topologyData, TopologyMap &topologyMap) {
auto request = this->getDrmParamValue(DrmParam::queryComputeSlices);
auto engineInfo = drm.getEngineInfo();
auto nTiles = hwInfo.gtSystemInfo.MultiTileArchInfo.TileCount;
auto useNewQuery = debugManager.flags.UseNewQueryTopoIoctl.get() &&
engineInfo &&
(nTiles > 0);
if (useNewQuery) {
bool success = true;
int sliceCount = 0;
int subSliceCount = 0;
int euCount = 0;
for (auto i = 0u; i < nTiles; i++) {
auto classInstance = engineInfo->getEngineInstance(i, hwInfo.capabilityTable.defaultEngineType);
UNRECOVERABLE_IF(!classInstance);
uint32_t flags = classInstance->engineClass;
flags |= (classInstance->engineInstance << 8);
auto dataQuery = drm.query<uint64_t>(request, flags);
if (dataQuery.empty()) {
success = false;
break;
}
auto data = reinterpret_cast<QueryTopologyInfo *>(dataQuery.data());
DrmQueryTopologyData tileTopologyData = {};
TopologyMapping mapping;
if (!this->translateTopologyInfo(data, tileTopologyData, mapping)) {
success = false;
break;
}
// pick smallest config
sliceCount = (sliceCount == 0) ? tileTopologyData.sliceCount : std::min(sliceCount, tileTopologyData.sliceCount);
subSliceCount = (subSliceCount == 0) ? tileTopologyData.subSliceCount : std::min(subSliceCount, tileTopologyData.subSliceCount);
euCount = (euCount == 0) ? tileTopologyData.euCount : std::min(euCount, tileTopologyData.euCount);
topologyData.maxSlices = std::max(topologyData.maxSlices, tileTopologyData.maxSlices);
topologyData.maxSubSlicesPerSlice = std::max(topologyData.maxSubSlicesPerSlice, tileTopologyData.maxSubSlicesPerSlice);
topologyData.maxEusPerSubSlice = std::max(topologyData.maxEusPerSubSlice, static_cast<int>(data->maxEusPerSubslice));
topologyMap[i] = mapping;
}
if (success) {
topologyData.sliceCount = sliceCount;
topologyData.subSliceCount = subSliceCount;
topologyData.euCount = euCount;
return true;
}
}
// fallback to DRM_I915_QUERY_TOPOLOGY_INFO
return IoctlHelperI915::getTopologyDataAndMap(hwInfo, topologyData, topologyMap);
}
bool IoctlHelperPrelim20::isVmBindAvailable() {
const auto &productHelper = drm.getRootDeviceEnvironment().getHelper<ProductHelper>();
if (!productHelper.isNewResidencyModelSupported()) {
return false;
}
int vmBindSupported = 0;
GetParam getParam{};
getParam.param = PRELIM_I915_PARAM_HAS_VM_BIND;
getParam.value = &vmBindSupported;
int retVal = IoctlHelper::ioctl(DrmIoctl::getparam, &getParam);
if (retVal) {
return false;
}
return vmBindSupported;
}
int IoctlHelperPrelim20::createGemExt(const MemRegionsVec &memClassInstances, size_t allocSize, uint32_t &handle, uint64_t patIndex, std::optional<uint32_t> vmId, int32_t pairHandle, bool isChunked, uint32_t numOfChunks, std::optional<uint32_t> memPolicyMode, std::optional<std::vector<unsigned long>> memPolicyNodemask, std::optional<bool> isCoherent) {
uint32_t regionsSize = static_cast<uint32_t>(memClassInstances.size());
std::vector<prelim_drm_i915_gem_memory_class_instance> regions(regionsSize);
for (uint32_t i = 0; i < regionsSize; i++) {
regions[i].memory_class = memClassInstances[i].memoryClass;
regions[i].memory_instance = memClassInstances[i].memoryInstance;
}
prelim_drm_i915_gem_object_param regionParam{};
regionParam.size = regionsSize;
regionParam.data = reinterpret_cast<uintptr_t>(regions.data());
regionParam.param = PRELIM_I915_OBJECT_PARAM | PRELIM_I915_PARAM_MEMORY_REGIONS;
prelim_drm_i915_gem_create_ext_setparam setparamRegion{};
setparamRegion.base.name = PRELIM_I915_GEM_CREATE_EXT_SETPARAM;
setparamRegion.param = regionParam;
prelim_drm_i915_gem_create_ext_vm_private vmPrivate{};
prelim_drm_i915_gem_create_ext_setparam pairSetparamRegion{};
prelim_drm_i915_gem_create_ext_setparam chunkingParamRegion{};
prelim_drm_i915_gem_create_ext_memory_policy memPolicy{};
if (vmId != std::nullopt) {
vmPrivate.base.name = PRELIM_I915_GEM_CREATE_EXT_VM_PRIVATE;
vmPrivate.vm_id = vmId.value();
}
if (memPolicyMode != std::nullopt) {
UNRECOVERABLE_IF(memPolicyNodemask == std::nullopt);
memPolicy.base.name = PRELIM_I915_GEM_CREATE_EXT_MEMORY_POLICY;
memPolicy.mode = memPolicyMode.value();
memPolicy.flags = 0;
memPolicy.nodemask_max = static_cast<uint32_t>(memPolicyNodemask.value().size());
memPolicy.nodemask_ptr = reinterpret_cast<uintptr_t>(memPolicyNodemask.value().data());
}
if (pairHandle != -1) {
pairSetparamRegion.base.name = PRELIM_I915_GEM_CREATE_EXT_SETPARAM;
pairSetparamRegion.param.param = PRELIM_I915_OBJECT_PARAM | PRELIM_I915_PARAM_SET_PAIR;
pairSetparamRegion.param.data = pairHandle;
}
size_t chunkingSize = 0u;
if (isChunked) {
chunkingSize = allocSize / numOfChunks;
chunkingParamRegion.base.name = PRELIM_I915_GEM_CREATE_EXT_SETPARAM;
chunkingParamRegion.param.param = PRELIM_I915_OBJECT_PARAM | PRELIM_I915_PARAM_SET_CHUNK_SIZE;
UNRECOVERABLE_IF(chunkingSize & (MemoryConstants::pageSize64k - 1));
chunkingParamRegion.param.data = chunkingSize;
setparamRegion.base.next_extension = reinterpret_cast<uintptr_t>(&chunkingParamRegion);
if (memPolicyMode != std::nullopt) {
chunkingParamRegion.base.next_extension = reinterpret_cast<uintptr_t>(&memPolicy);
}
} else {
auto *lastExtension = &(setparamRegion.base);
if (vmId != std::nullopt) {
setparamRegion.base.next_extension = reinterpret_cast<uintptr_t>(&vmPrivate);
lastExtension = &(vmPrivate.base);
}
if (pairHandle != -1) {
lastExtension->next_extension = reinterpret_cast<uintptr_t>(&pairSetparamRegion);
lastExtension = &(pairSetparamRegion.base);
}
if (memPolicyMode != std::nullopt) {
lastExtension->next_extension = reinterpret_cast<uintptr_t>(&memPolicy);
}
}
prelim_drm_i915_gem_create_ext createExt{};
createExt.size = allocSize;
createExt.extensions = reinterpret_cast<uintptr_t>(&setparamRegion);
printDebugString(debugManager.flags.PrintBOCreateDestroyResult.get(), stdout, "Performing GEM_CREATE_EXT with { size: %lu, param: 0x%llX",
allocSize, regionParam.param);
if (debugManager.flags.PrintBOCreateDestroyResult.get()) {
for (uint32_t i = 0; i < regionsSize; i++) {
auto region = regions[i];
printDebugString(debugManager.flags.PrintBOCreateDestroyResult.get(), stdout, ", memory class: %d, memory instance: %d",
region.memory_class, region.memory_instance);
}
if (memPolicyMode != std::nullopt) {
printDebugString(debugManager.flags.PrintBOCreateDestroyResult.get(), stdout,
", memory policy:{ mode: %d, nodemask_max: 0x%d, nodemask_ptr: 0x%llX }",
memPolicy.mode,
memPolicy.nodemask_max,
memPolicy.nodemask_ptr);
}
printDebugString(debugManager.flags.PrintBOCreateDestroyResult.get(), stdout, "%s", " }\n");
}
auto ret = ioctl(DrmIoctl::gemCreateExt, &createExt);
if (isChunked) {
printDebugString(debugManager.flags.PrintBOChunkingLogs.get(), stdout,
"GEM_CREATE_EXT BO-%d with BOChunkingSize %d, chunkingParamRegion.param.data %d, numOfChunks %d\n",
createExt.handle,
chunkingSize,
chunkingParamRegion.param.data,
numOfChunks);
}
printDebugString(debugManager.flags.PrintBOCreateDestroyResult.get(), stdout, "GEM_CREATE_EXT has returned: %d BO-%u with size: %lu\n", ret, createExt.handle, createExt.size);
handle = createExt.handle;
return ret;
}
CacheRegion IoctlHelperPrelim20::closAlloc(CacheLevel cacheLevel) {
struct prelim_drm_i915_gem_clos_reserve clos = {};
int ret = IoctlHelper::ioctl(DrmIoctl::gemClosReserve, &clos);
if (ret != 0) {
int err = errno;
printDebugString(debugManager.flags.PrintDebugMessages.get(), stderr, "ioctl(I915_GEM_CLOS_RESERVE) failed with %d. errno=%d(%s)\n", ret, err, strerror(err));
DEBUG_BREAK_IF(true);
return CacheRegion::none;
}
return static_cast<CacheRegion>(clos.clos_index);
}
uint16_t IoctlHelperPrelim20::closAllocWays(CacheRegion closIndex, uint16_t cacheLevel, uint16_t numWays) {
struct prelim_drm_i915_gem_cache_reserve cache = {};
cache.clos_index = static_cast<uint16_t>(closIndex);
cache.cache_level = cacheLevel;
cache.num_ways = numWays;
int ret = IoctlHelper::ioctl(DrmIoctl::gemCacheReserve, &cache);
if (ret != 0) {
int err = errno;
PRINT_DEBUG_STRING(debugManager.flags.PrintDebugMessages.get(), stderr, "ioctl(I915_GEM_CACHE_RESERVE) failed with %d. errno=%d(%s)\n", ret, err, strerror(err));
return 0;
}
return cache.num_ways;
}
CacheRegion IoctlHelperPrelim20::closFree(CacheRegion closIndex) {
struct prelim_drm_i915_gem_clos_free clos = {};
clos.clos_index = static_cast<uint16_t>(closIndex);
int ret = IoctlHelper::ioctl(DrmIoctl::gemClosFree, &clos);
if (ret != 0) {
int err = errno;
printDebugString(debugManager.flags.PrintDebugMessages.get(), stderr, "ioctl(I915_GEM_CLOS_FREE) failed with %d. errno=%d(%s)\n", ret, err, strerror(err));
DEBUG_BREAK_IF(true);
return CacheRegion::none;
}
return closIndex;
}
int IoctlHelperPrelim20::waitUserFence(uint32_t ctxId, uint64_t address,
uint64_t value, uint32_t dataWidth, int64_t timeout, uint16_t flags,
bool userInterrupt, uint32_t externalInterruptId, GraphicsAllocation *allocForInterruptWait) {
prelim_drm_i915_gem_wait_user_fence wait = {};
wait.ctx_id = ctxId;
wait.flags = flags;
switch (dataWidth) {
case 3u:
wait.mask = PRELIM_I915_UFENCE_WAIT_U64;
break;
case 2u:
wait.mask = PRELIM_I915_UFENCE_WAIT_U32;
break;
case 1u:
wait.mask = PRELIM_I915_UFENCE_WAIT_U16;
break;
default:
wait.mask = PRELIM_I915_UFENCE_WAIT_U8;
break;
}
wait.op = PRELIM_I915_UFENCE_WAIT_GTE;
wait.addr = address;
wait.value = value;
wait.timeout = timeout;
return IoctlHelper::ioctl(DrmIoctl::gemWaitUserFence, &wait);
}
uint32_t IoctlHelperPrelim20::getAtomicAdvise(bool isNonAtomic) {
return isNonAtomic ? PRELIM_I915_VM_ADVISE_ATOMIC_NONE : PRELIM_I915_VM_ADVISE_ATOMIC_SYSTEM;
}
uint32_t IoctlHelperPrelim20::getAtomicAccess(AtomicAccessMode mode) {
uint32_t retVal = 0;
switch (mode) {
case AtomicAccessMode::device:
retVal = PRELIM_I915_VM_ADVISE_ATOMIC_DEVICE;
break;
case AtomicAccessMode::system:
retVal = PRELIM_I915_VM_ADVISE_ATOMIC_SYSTEM;
break;
case AtomicAccessMode::none:
retVal = PRELIM_I915_VM_ADVISE_ATOMIC_NONE;
break;
case AtomicAccessMode::host:
default:
break;
}
return retVal;
}
uint32_t IoctlHelperPrelim20::getPreferredLocationAdvise() {
return PRELIM_I915_VM_ADVISE_PREFERRED_LOCATION;
}
std::optional<MemoryClassInstance> IoctlHelperPrelim20::getPreferredLocationRegion(PreferredLocation memoryLocation, uint32_t memoryInstance) {
MemoryClassInstance region{};
if (NEO::debugManager.flags.SetVmAdvisePreferredLocation.get() != -1) {
memoryLocation = static_cast<PreferredLocation>(NEO::debugManager.flags.SetVmAdvisePreferredLocation.get());
}
switch (memoryLocation) {
case PreferredLocation::clear:
region.memoryClass = -1;
region.memoryInstance = 0;
break;
case PreferredLocation::system:
region.memoryClass = getDrmParamValue(DrmParam::memoryClassSystem);
region.memoryInstance = 0;
break;
case PreferredLocation::device:
default:
region.memoryClass = getDrmParamValue(DrmParam::memoryClassDevice);
region.memoryInstance = memoryInstance;
break;
case PreferredLocation::none:
return std::nullopt;
}
return region;
}
bool IoctlHelperPrelim20::setVmBoAdviseForChunking(int32_t handle, uint64_t start, uint64_t length, uint32_t attribute, void *region) {
prelim_drm_i915_gem_vm_advise vmAdvise{};
vmAdvise.handle = handle;
vmAdvise.start = start;
vmAdvise.length = length;
vmAdvise.attribute = attribute;
UNRECOVERABLE_IF(region == nullptr);
vmAdvise.region = *reinterpret_cast<prelim_drm_i915_gem_memory_class_instance *>(region);
int ret = IoctlHelper::ioctl(DrmIoctl::gemVmAdvise, &vmAdvise);
if (ret != 0) {
int err = errno;
CREATE_DEBUG_STRING(str, "ioctl(PRELIM_DRM_I915_GEM_VM_ADVISE) failed with %d. errno=%d(%s)\n", ret, err, strerror(err));
drm.getRootDeviceEnvironment().executionEnvironment.setErrorDescription(std::string(str.get()));
PRINT_DEBUG_STRING(debugManager.flags.PrintDebugMessages.get(), stderr, str.get());
DEBUG_BREAK_IF(true);
return false;
}
return true;
}
bool IoctlHelperPrelim20::setVmBoAdvise(int32_t handle, uint32_t attribute, void *region) {
prelim_drm_i915_gem_vm_advise vmAdvise{};
vmAdvise.handle = handle;
vmAdvise.attribute = attribute;
if (region != nullptr) {
vmAdvise.region = *reinterpret_cast<prelim_drm_i915_gem_memory_class_instance *>(region);
}
int ret = IoctlHelper::ioctl(DrmIoctl::gemVmAdvise, &vmAdvise);
if (ret != 0) {
int err = errno;
CREATE_DEBUG_STRING(str, "ioctl(PRELIM_DRM_I915_GEM_VM_ADVISE) failed with %d. errno=%d(%s)\n", ret, err, strerror(err));
drm.getRootDeviceEnvironment().executionEnvironment.setErrorDescription(std::string(str.get()));
PRINT_DEBUG_STRING(debugManager.flags.PrintDebugMessages.get(), stderr, str.get());
DEBUG_BREAK_IF(true);
return false;
}
return true;
}
bool IoctlHelperPrelim20::setVmPrefetch(uint64_t start, uint64_t length, uint32_t region, uint32_t vmId) {
prelim_drm_i915_gem_vm_prefetch vmPrefetch{};
vmPrefetch.length = length;
vmPrefetch.region = region;
vmPrefetch.start = start;
vmPrefetch.vm_id = vmId;
int ret = IoctlHelper::ioctl(DrmIoctl::gemVmPrefetch, &vmPrefetch);
if (ret != 0) {
int err = errno;
CREATE_DEBUG_STRING(str, "ioctl(PRELIM_DRM_I915_GEM_VM_PREFETCH) failed with %d. errno=%d(%s)\n", ret, err, strerror(err));
drm.getRootDeviceEnvironment().executionEnvironment.setErrorDescription(std::string(str.get()));
PRINT_DEBUG_STRING(debugManager.flags.PrintDebugMessages.get(), stderr, str.get());
DEBUG_BREAK_IF(true);
return false;
}
return true;
}
uint32_t IoctlHelperPrelim20::getDirectSubmissionFlag() {
return PRELIM_I915_CONTEXT_CREATE_FLAGS_LONG_RUNNING;
}
uint16_t IoctlHelperPrelim20::getWaitUserFenceSoftFlag() {
return PRELIM_I915_UFENCE_WAIT_SOFT;
};
int IoctlHelperPrelim20::execBuffer(ExecBuffer *execBuffer, uint64_t completionGpuAddress, TaskCountType counterValue) {
prelim_drm_i915_gem_execbuffer_ext_user_fence fenceObject = {};
if (completionGpuAddress != 0) {
fenceObject.base.name = PRELIM_DRM_I915_GEM_EXECBUFFER_EXT_USER_FENCE;
fenceObject.addr = completionGpuAddress;
fenceObject.value = counterValue;
auto &drmExecBuffer = *reinterpret_cast<drm_i915_gem_execbuffer2 *>(execBuffer->data);
drmExecBuffer.flags |= I915_EXEC_USE_EXTENSIONS;
drmExecBuffer.num_cliprects = 0;
drmExecBuffer.cliprects_ptr = castToUint64(&fenceObject);
if (debugManager.flags.PrintCompletionFenceUsage.get()) {
std::cout << "Completion fence submitted."
<< " GPU address: " << std::hex << completionGpuAddress << std::dec
<< ", value: " << counterValue << std::endl;
}
}
return IoctlHelper::ioctl(DrmIoctl::gemExecbuffer2, execBuffer);
}
bool IoctlHelperPrelim20::completionFenceExtensionSupported(const bool isVmBindAvailable) {
return isVmBindAvailable;
}
std::unique_ptr<uint8_t[]> IoctlHelperPrelim20::prepareVmBindExt(const StackVec<uint32_t, 2> &bindExtHandles, uint32_t vmHandleId) {
static_assert(std::is_trivially_destructible_v<prelim_drm_i915_vm_bind_ext_uuid>,
"Storage must be allowed to be reused without calling the destructor!");
static_assert(alignof(prelim_drm_i915_vm_bind_ext_uuid) <= __STDCPP_DEFAULT_NEW_ALIGNMENT__,
"Alignment of a buffer returned via new[] operator must allow storing the required type!");
const auto bufferSize{sizeof(prelim_drm_i915_vm_bind_ext_uuid) * bindExtHandles.size()};
std::unique_ptr<uint8_t[]> extensionsBuffer{new uint8_t[bufferSize]};
auto extensions = new (extensionsBuffer.get()) prelim_drm_i915_vm_bind_ext_uuid[bindExtHandles.size()];
std::memset(extensionsBuffer.get(), 0, bufferSize);
extensions[0].uuid_handle = bindExtHandles[0];
extensions[0].base.name = PRELIM_I915_VM_BIND_EXT_UUID;
for (size_t i = 1; i < bindExtHandles.size(); i++) {
extensions[i - 1].base.next_extension = reinterpret_cast<uint64_t>(&extensions[i]);
extensions[i].uuid_handle = bindExtHandles[i];
extensions[i].base.name = PRELIM_I915_VM_BIND_EXT_UUID;
}
return extensionsBuffer;
}
uint64_t IoctlHelperPrelim20::getFlagsForVmBind(bool bindCapture, bool bindImmediate, bool bindMakeResident, bool bindLockedMemory, bool readOnlyResource) {
uint64_t flags = 0u;
if (bindCapture) {
flags |= PRELIM_I915_GEM_VM_BIND_CAPTURE;
}
if (bindImmediate) {
flags |= PRELIM_I915_GEM_VM_BIND_IMMEDIATE;
}
if (bindMakeResident || bindLockedMemory) { // lockedMemory is equal to residency in i915_prelim
flags |= PRELIM_I915_GEM_VM_BIND_MAKE_RESIDENT;
}
if (readOnlyResource) {
flags |= PRELIM_I915_GEM_VM_BIND_READONLY;
}
return flags;
}
prelim_drm_i915_query_distance_info translateToi915(const DistanceInfo &distanceInfo) {
prelim_drm_i915_query_distance_info dist{};
dist.engine.engine_class = distanceInfo.engine.engineClass;
dist.engine.engine_instance = distanceInfo.engine.engineInstance;
dist.region.memory_class = distanceInfo.region.memoryClass;
dist.region.memory_instance = distanceInfo.region.memoryInstance;
return dist;
}
int IoctlHelperPrelim20::queryDistances(std::vector<QueryItem> &queryItems, std::vector<DistanceInfo> &distanceInfos) {
std::vector<prelim_drm_i915_query_distance_info> i915Distances(distanceInfos.size());
std::transform(distanceInfos.begin(), distanceInfos.end(), i915Distances.begin(), translateToi915);
for (auto i = 0u; i < i915Distances.size(); i++) {
queryItems[i].queryId = PRELIM_DRM_I915_QUERY_DISTANCE_INFO;
queryItems[i].length = sizeof(prelim_drm_i915_query_distance_info);
queryItems[i].flags = 0u;
queryItems[i].dataPtr = reinterpret_cast<uint64_t>(&i915Distances[i]);
}
Query query{};
query.itemsPtr = reinterpret_cast<uint64_t>(queryItems.data());
query.numItems = static_cast<uint32_t>(queryItems.size());
auto ret = IoctlHelper::ioctl(DrmIoctl::query, &query);
for (auto i = 0u; i < i915Distances.size(); i++) {
queryItems[i].dataPtr = 0u;
distanceInfos[i].distance = i915Distances[i].distance;
}
return ret;
}
bool IoctlHelperPrelim20::isPageFaultSupported() {
int pagefaultSupport{};
GetParam getParam{};
getParam.param = PRELIM_I915_PARAM_HAS_PAGE_FAULT;
getParam.value = &pagefaultSupport;
int retVal = ioctl(DrmIoctl::getparam, &getParam);
if (debugManager.flags.PrintIoctlEntries.get()) {
printf("DRM_IOCTL_I915_GETPARAM: param: PRELIM_I915_PARAM_HAS_PAGE_FAULT, output value: %d, retCode:% d\n",
*getParam.value,
retVal);
}
return (retVal == 0) && (pagefaultSupport > 0);
};
bool IoctlHelperPrelim20::isEuStallSupported() {
return true;
}
bool IoctlHelperPrelim20::getEuStallProperties(std::array<uint64_t, 12u> &properties, uint64_t dssBufferSize, uint64_t samplingRate,
uint64_t pollPeriod, uint64_t engineInstance, uint64_t notifyNReports) {
properties[0] = prelim_drm_i915_eu_stall_property_id::PRELIM_DRM_I915_EU_STALL_PROP_BUF_SZ;
properties[1] = dssBufferSize;
properties[2] = prelim_drm_i915_eu_stall_property_id::PRELIM_DRM_I915_EU_STALL_PROP_SAMPLE_RATE;
properties[3] = samplingRate;
properties[4] = prelim_drm_i915_eu_stall_property_id::PRELIM_DRM_I915_EU_STALL_PROP_POLL_PERIOD;
properties[5] = pollPeriod;
properties[6] = prelim_drm_i915_eu_stall_property_id::PRELIM_DRM_I915_EU_STALL_PROP_ENGINE_CLASS;
properties[7] = prelim_drm_i915_gem_engine_class::PRELIM_I915_ENGINE_CLASS_COMPUTE;
properties[8] = prelim_drm_i915_eu_stall_property_id::PRELIM_DRM_I915_EU_STALL_PROP_ENGINE_INSTANCE;
properties[9] = engineInstance;
properties[10] = prelim_drm_i915_eu_stall_property_id::PRELIM_DRM_I915_EU_STALL_PROP_EVENT_REPORT_COUNT;
properties[11] = notifyNReports;
return true;
}
uint32_t IoctlHelperPrelim20::getEuStallFdParameter() {
return PRELIM_I915_PERF_FLAG_FD_EU_STALL;
}
bool IoctlHelperPrelim20::perfOpenEuStallStream(uint32_t euStallFdParameter, std::array<uint64_t, 12u> &properties, int32_t *stream) {
NEO::PrelimI915::drm_i915_perf_open_param param = {};
param.flags = I915_PERF_FLAG_FD_CLOEXEC |
euStallFdParameter |
I915_PERF_FLAG_FD_NONBLOCK;
param.num_properties = sizeof(properties) / 16;
param.properties_ptr = reinterpret_cast<uintptr_t>(properties.data());
*stream = ioctl(DrmIoctl::perfOpen, &param);
if (*stream < 0) {
PRINT_DEBUG_STRING(NEO::debugManager.flags.PrintDebugMessages.get() && (*stream < 0), stderr,
"%s failed errno = %d | ret = %d \n", "DRM_IOCTL_I915_PERF_OPEN", errno, *stream);
return false;
}
auto ret = ioctl(*stream, DrmIoctl::perfEnable, 0);
PRINT_DEBUG_STRING(NEO::debugManager.flags.PrintDebugMessages.get() && (ret < 0), stderr,
"%s failed errno = %d | ret = %d \n", "I915_PERF_IOCTL_ENABLE", errno, ret);
return (ret == 0) ? true : false;
}
bool IoctlHelperPrelim20::perfDisableEuStallStream(int32_t *stream) {
int disableStatus = ioctl(*stream, DrmIoctl::perfDisable, 0);
PRINT_DEBUG_STRING(NEO::debugManager.flags.PrintDebugMessages.get() && (disableStatus < 0), stderr,
"I915_PERF_IOCTL_DISABLE failed errno = %d | ret = %d \n", errno, disableStatus);
int closeStatus = NEO::SysCalls::close(*stream);
PRINT_DEBUG_STRING(NEO::debugManager.flags.PrintDebugMessages.get() && (closeStatus < 0), stderr,
"close() failed errno = %d | ret = %d \n", errno, closeStatus);
*stream = -1;
return ((closeStatus == 0) && (disableStatus == 0)) ? true : false;
}
std::unique_ptr<uint8_t[]> IoctlHelperPrelim20::createVmControlExtRegion(const std::optional<MemoryClassInstance> &regionInstanceClass) {
if (regionInstanceClass) {
auto retVal = std::make_unique<uint8_t[]>(sizeof(prelim_drm_i915_gem_vm_region_ext));
auto regionExt = reinterpret_cast<prelim_drm_i915_gem_vm_region_ext *>(retVal.get());
*regionExt = {};
regionExt->base.name = PRELIM_I915_GEM_VM_CONTROL_EXT_REGION;
regionExt->region.memory_class = regionInstanceClass.value().memoryClass;
regionExt->region.memory_instance = regionInstanceClass.value().memoryInstance;
return retVal;
}
return {};
}
uint32_t IoctlHelperPrelim20::getFlagsForVmCreate(bool disableScratch, bool enablePageFault, bool useVmBind) {
uint32_t flags = 0u;
if (disableScratch) {
flags |= PRELIM_I915_VM_CREATE_FLAGS_DISABLE_SCRATCH;
}
if (enablePageFault) {
flags |= PRELIM_I915_VM_CREATE_FLAGS_ENABLE_PAGE_FAULT;
}
if (useVmBind) {
flags |= PRELIM_I915_VM_CREATE_FLAGS_USE_VM_BIND;
}
return flags;
}
uint32_t gemCreateContextExt(IoctlHelper &ioctlHelper, GemContextCreateExt &gcc, GemContextCreateExtSetParam &extSetparam) {
gcc.flags |= I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS;
extSetparam.base.nextExtension = gcc.extensions;
gcc.extensions = reinterpret_cast<uint64_t>(&extSetparam);
auto ioctlResult = ioctlHelper.ioctl(DrmIoctl::gemContextCreateExt, &gcc);
UNRECOVERABLE_IF(ioctlResult != 0);
return gcc.contextId;
}
uint32_t gemCreateContextAcc(IoctlHelper &ioctlHelper, GemContextCreateExt &gcc, uint16_t trigger, uint8_t granularity) {
prelim_drm_i915_gem_context_param_acc paramAcc = {};
paramAcc.trigger = trigger;
paramAcc.notify = 1;
paramAcc.granularity = granularity;
DrmUserExtension userExt{};
userExt.name = I915_CONTEXT_CREATE_EXT_SETPARAM;
GemContextParam ctxParam = {};
ctxParam.param = PRELIM_I915_CONTEXT_PARAM_ACC;
ctxParam.contextId = 0;
ctxParam.size = sizeof(paramAcc);
ctxParam.value = reinterpret_cast<uint64_t>(&paramAcc);
GemContextCreateExtSetParam extSetparam{};
extSetparam.base = userExt;
extSetparam.param = ctxParam;
return gemCreateContextExt(ioctlHelper, gcc, extSetparam);
}
uint32_t IoctlHelperPrelim20::createContextWithAccessCounters(GemContextCreateExt &gcc) {
uint16_t trigger = 0;
if (debugManager.flags.AccessCountersTrigger.get() != -1) {
trigger = static_cast<uint16_t>(debugManager.flags.AccessCountersTrigger.get());
}
uint8_t granularity = PRELIM_I915_CONTEXT_ACG_2M;
if (debugManager.flags.AccessCountersGranularity.get() != -1) {
granularity = static_cast<uint8_t>(debugManager.flags.AccessCountersGranularity.get());
}
return gemCreateContextAcc(*this, gcc, trigger, granularity);
}
uint32_t IoctlHelperPrelim20::createCooperativeContext(GemContextCreateExt &gcc) {
GemContextCreateExtSetParam extSetparam{};
extSetparam.base.name = I915_CONTEXT_CREATE_EXT_SETPARAM;
extSetparam.param.param = PRELIM_I915_CONTEXT_PARAM_RUNALONE;
return gemCreateContextExt(*this, gcc, extSetparam);
}
static_assert(sizeof(VmBindExtSetPatT) == sizeof(prelim_drm_i915_vm_bind_ext_set_pat), "Invalid size for VmBindExtSetPat");
void IoctlHelperPrelim20::fillVmBindExtSetPat(VmBindExtSetPatT &vmBindExtSetPat, uint64_t patIndex, uint64_t nextExtension) {
auto prelimVmBindExtSetPat = reinterpret_cast<prelim_drm_i915_vm_bind_ext_set_pat *>(vmBindExtSetPat);
UNRECOVERABLE_IF(!prelimVmBindExtSetPat);
prelimVmBindExtSetPat->base.name = PRELIM_I915_VM_BIND_EXT_SET_PAT;
prelimVmBindExtSetPat->pat_index = patIndex;
prelimVmBindExtSetPat->base.next_extension = nextExtension;
}
static_assert(sizeof(VmBindExtUserFenceT) == sizeof(prelim_drm_i915_vm_bind_ext_user_fence), "Invalid size for VmBindExtUserFence");
void IoctlHelperPrelim20::fillVmBindExtUserFence(VmBindExtUserFenceT &vmBindExtUserFence, uint64_t fenceAddress, uint64_t fenceValue, uint64_t nextExtension) {
auto prelimVmBindExtUserFence = reinterpret_cast<prelim_drm_i915_vm_bind_ext_user_fence *>(vmBindExtUserFence);
UNRECOVERABLE_IF(!prelimVmBindExtUserFence);
prelimVmBindExtUserFence->base.name = PRELIM_I915_VM_BIND_EXT_USER_FENCE;
prelimVmBindExtUserFence->base.next_extension = nextExtension;
prelimVmBindExtUserFence->addr = fenceAddress;
prelimVmBindExtUserFence->val = fenceValue;
}
void IoctlHelperPrelim20::setVmBindUserFence(VmBindParams &vmBind, VmBindExtUserFenceT vmBindUserFence) {
vmBind.extensions = castToUint64(vmBindUserFence);
return;
}
EngineCapabilities::Flags IoctlHelperPrelim20::getEngineCapabilitiesFlags(uint64_t capabilities) const {
EngineCapabilities::Flags flags{};
flags.copyClassSaturateLink = isValueSet(capabilities, PRELIM_I915_COPY_CLASS_CAP_SATURATE_LINK);
flags.copyClassSaturatePCIE = isValueSet(capabilities, PRELIM_I915_COPY_CLASS_CAP_SATURATE_PCIE);
return flags;
}
std::optional<uint32_t> IoctlHelperPrelim20::getVmAdviseAtomicAttribute() {
switch (NEO::debugManager.flags.SetVmAdviseAtomicAttribute.get()) {
case 0:
return PRELIM_I915_VM_ADVISE_ATOMIC_NONE;
case 1:
return PRELIM_I915_VM_ADVISE_ATOMIC_DEVICE;
default:
return PRELIM_I915_VM_ADVISE_ATOMIC_SYSTEM;
}
}
prelim_drm_i915_gem_vm_bind translateVmBindParamsToPrelimStruct(const VmBindParams &vmBindParams) {
prelim_drm_i915_gem_vm_bind vmBind{};
vmBind.vm_id = vmBindParams.vmId;
vmBind.handle = vmBindParams.handle;
vmBind.start = vmBindParams.start;
vmBind.offset = vmBindParams.offset;
vmBind.length = vmBindParams.length;
vmBind.flags = vmBindParams.flags;
vmBind.extensions = vmBindParams.extensions;
return vmBind;
}
int IoctlHelperPrelim20::vmBind(const VmBindParams &vmBindParams) {
auto prelimVmBind = translateVmBindParamsToPrelimStruct(vmBindParams);
return IoctlHelper::ioctl(DrmIoctl::gemVmBind, &prelimVmBind);
}
int IoctlHelperPrelim20::vmUnbind(const VmBindParams &vmBindParams) {
auto prelimVmBind = translateVmBindParamsToPrelimStruct(vmBindParams);
return IoctlHelper::ioctl(DrmIoctl::gemVmUnbind, &prelimVmBind);
}
int IoctlHelperPrelim20::getResetStats(ResetStats &resetStats, uint32_t *status, ResetStatsFault *resetStatsFault) {
prelim_drm_i915_reset_stats prelimResetStats{};
prelimResetStats.ctx_id = resetStats.contextId;
prelimResetStats.flags = resetStats.flags;
const auto retVal = ioctl(DrmIoctl::getResetStatsPrelim, &prelimResetStats);
if (retVal != 0) {
return ioctl(DrmIoctl::getResetStats, &resetStats);
}
resetStats.resetCount = prelimResetStats.reset_count;
resetStats.batchActive = prelimResetStats.batch_active;
resetStats.batchPending = prelimResetStats.batch_pending;
if (status) {
*status = prelimResetStats.status;
}
if (resetStatsFault) {
auto fault = reinterpret_cast<ResetStatsFault *>(&(prelimResetStats.fault));
*resetStatsFault = *fault;
}
return retVal;
}
UuidRegisterResult IoctlHelperPrelim20::registerUuid(const std::string &uuid, uint32_t uuidClass, uint64_t ptr, uint64_t size) {
prelim_drm_i915_uuid_control uuidControl = {};
memcpy_s(uuidControl.uuid, sizeof(uuidControl.uuid), uuid.c_str(), uuid.size());
uuidControl.uuid_class = uuidClass;
uuidControl.ptr = ptr;
uuidControl.size = size;
const auto retVal = IoctlHelper::ioctl(DrmIoctl::uuidRegister, &uuidControl);
return {
retVal,
uuidControl.handle,
};
}
UuidRegisterResult IoctlHelperPrelim20::registerStringClassUuid(const std::string &uuid, uint64_t ptr, uint64_t size) {
return registerUuid(uuid, PRELIM_I915_UUID_CLASS_STRING, ptr, size);
}
int IoctlHelperPrelim20::unregisterUuid(uint32_t handle) {
prelim_drm_i915_uuid_control uuidControl = {};
uuidControl.handle = handle;
return IoctlHelper::ioctl(DrmIoctl::uuidUnregister, &uuidControl);
}
bool IoctlHelperPrelim20::isContextDebugSupported() {
GemContextParam ctxParam = {};
ctxParam.size = 0;
ctxParam.param = PRELIM_I915_CONTEXT_PARAM_DEBUG_FLAGS;
ctxParam.contextId = 0;
ctxParam.value = 0;
const auto retVal = IoctlHelper::ioctl(DrmIoctl::gemContextGetparam, &ctxParam);
return retVal == 0 && ctxParam.value == (PRELIM_I915_CONTEXT_PARAM_DEBUG_FLAG_SIP << 32);
}
int IoctlHelperPrelim20::setContextDebugFlag(uint32_t drmContextId) {
GemContextParam ctxParam = {};
ctxParam.size = 0;
ctxParam.param = PRELIM_I915_CONTEXT_PARAM_DEBUG_FLAGS;
ctxParam.contextId = drmContextId;
ctxParam.value = PRELIM_I915_CONTEXT_PARAM_DEBUG_FLAG_SIP << 32 | PRELIM_I915_CONTEXT_PARAM_DEBUG_FLAG_SIP;
return IoctlHelper::ioctl(DrmIoctl::gemContextSetparam, &ctxParam);
}
bool IoctlHelperPrelim20::isDebugAttachAvailable() {
return true;
}
unsigned int IoctlHelperPrelim20::getIoctlRequestValue(DrmIoctl ioctlRequest) const {
switch (ioctlRequest) {
case DrmIoctl::gemVmBind:
return PRELIM_DRM_IOCTL_I915_GEM_VM_BIND;
case DrmIoctl::gemVmUnbind:
return PRELIM_DRM_IOCTL_I915_GEM_VM_UNBIND;
case DrmIoctl::gemWaitUserFence:
return PRELIM_DRM_IOCTL_I915_GEM_WAIT_USER_FENCE;
case DrmIoctl::gemCreateExt:
return PRELIM_DRM_IOCTL_I915_GEM_CREATE_EXT;
case DrmIoctl::gemVmAdvise:
return PRELIM_DRM_IOCTL_I915_GEM_VM_ADVISE;
case DrmIoctl::gemVmPrefetch:
return PRELIM_DRM_IOCTL_I915_GEM_VM_PREFETCH;
case DrmIoctl::uuidRegister:
return PRELIM_DRM_IOCTL_I915_UUID_REGISTER;
case DrmIoctl::uuidUnregister:
return PRELIM_DRM_IOCTL_I915_UUID_UNREGISTER;
case DrmIoctl::debuggerOpen:
return PRELIM_DRM_IOCTL_I915_DEBUGGER_OPEN;
case DrmIoctl::gemClosReserve:
return PRELIM_DRM_IOCTL_I915_GEM_CLOS_RESERVE;
case DrmIoctl::gemClosFree:
return PRELIM_DRM_IOCTL_I915_GEM_CLOS_FREE;
case DrmIoctl::gemCacheReserve:
return PRELIM_DRM_IOCTL_I915_GEM_CACHE_RESERVE;
case DrmIoctl::getResetStatsPrelim:
return PRELIM_DRM_IOCTL_I915_GET_RESET_STATS;
default:
return IoctlHelperI915::getIoctlRequestValue(ioctlRequest);
}
}
int IoctlHelperPrelim20::getDrmParamValue(DrmParam drmParam) const {
switch (drmParam) {
case DrmParam::engineClassCompute:
return prelim_drm_i915_gem_engine_class::PRELIM_I915_ENGINE_CLASS_COMPUTE;
case DrmParam::paramHasVmBind:
return PRELIM_I915_PARAM_HAS_VM_BIND;
case DrmParam::paramHasPageFault:
return PRELIM_I915_PARAM_HAS_PAGE_FAULT;
case DrmParam::queryHwconfigTable:
return PRELIM_DRM_I915_QUERY_HWCONFIG_TABLE;
case DrmParam::queryComputeSlices:
return PRELIM_DRM_I915_QUERY_COMPUTE_SUBSLICES;
default:
return IoctlHelperI915::getDrmParamValueBase(drmParam);
}
}
std::string IoctlHelperPrelim20::getDrmParamString(DrmParam drmParam) const {
switch (drmParam) {
case DrmParam::paramHasVmBind:
return "PRELIM_I915_PARAM_HAS_VM_BIND";
case DrmParam::paramHasPageFault:
return "PRELIM_I915_PARAM_HAS_PAGE_FAULT";
default:
return IoctlHelperI915::getDrmParamString(drmParam);
}
}
std::string IoctlHelperPrelim20::getIoctlString(DrmIoctl ioctlRequest) const {
switch (ioctlRequest) {
case DrmIoctl::gemVmBind:
return "PRELIM_DRM_IOCTL_I915_GEM_VM_BIND";
case DrmIoctl::gemVmUnbind:
return "PRELIM_DRM_IOCTL_I915_GEM_VM_UNBIND";
case DrmIoctl::gemWaitUserFence:
return "PRELIM_DRM_IOCTL_I915_GEM_WAIT_USER_FENCE";
case DrmIoctl::gemCreateExt:
return "PRELIM_DRM_IOCTL_I915_GEM_CREATE_EXT";
case DrmIoctl::gemVmAdvise:
return "PRELIM_DRM_IOCTL_I915_GEM_VM_ADVISE";
case DrmIoctl::gemVmPrefetch:
return "PRELIM_DRM_IOCTL_I915_GEM_VM_PREFETCH";
case DrmIoctl::uuidRegister:
return "PRELIM_DRM_IOCTL_I915_UUID_REGISTER";
case DrmIoctl::uuidUnregister:
return "PRELIM_DRM_IOCTL_I915_UUID_UNREGISTER";
case DrmIoctl::debuggerOpen:
return "PRELIM_DRM_IOCTL_I915_DEBUGGER_OPEN";
case DrmIoctl::gemClosReserve:
return "PRELIM_DRM_IOCTL_I915_GEM_CLOS_RESERVE";
case DrmIoctl::gemClosFree:
return "PRELIM_DRM_IOCTL_I915_GEM_CLOS_FREE";
case DrmIoctl::gemCacheReserve:
return "PRELIM_DRM_IOCTL_I915_GEM_CACHE_RESERVE";
case DrmIoctl::getResetStatsPrelim:
return "PRELIM_DRM_IOCTL_I915_GET_RESET_STATS";
default:
return IoctlHelperI915::getIoctlString(ioctlRequest);
}
}
bool IoctlHelperPrelim20::checkIfIoctlReinvokeRequired(int error, DrmIoctl ioctlRequest) const {
switch (ioctlRequest) {
case DrmIoctl::debuggerOpen:
return (error == EINTR || error == EAGAIN);
case DrmIoctl::gemExecbuffer2:
if (handleExecBufferInNonBlockMode) {
return (error == EINTR || error == EBUSY || error == -EBUSY);
} else {
return IoctlHelper::checkIfIoctlReinvokeRequired(error, ioctlRequest);
}
default:
break;
}
return IoctlHelper::checkIfIoctlReinvokeRequired(error, ioctlRequest);
}
bool IoctlHelperPrelim20::getFabricLatency(uint32_t fabricId, uint32_t &latency, uint32_t &bandwidth) {
Query query = {};
QueryItem queryItem = {};
PrelimI915::prelim_drm_i915_query_fabric_info info = {};
info.fabric_id = fabricId;
queryItem.queryId = PRELIM_DRM_I915_QUERY_FABRIC_INFO;
queryItem.length = static_cast<int32_t>(sizeof(info));
queryItem.dataPtr = reinterpret_cast<uint64_t>(&info);
queryItem.flags = 0;
query.itemsPtr = reinterpret_cast<uint64_t>(&queryItem);
query.numItems = 1;
auto ret = IoctlHelper::ioctl(DrmIoctl::query, &query);
if (ret != 0) {
return false;
}
if (info.latency < 10 || info.bandwidth == 0) {
return false;
}
// Latency is in tenths of path length. 10 == 1 fabric link between src and dst
// 1 link = zero hops
latency = (info.latency / 10) - 1;
bandwidth = info.bandwidth;
return true;
}
bool IoctlHelperPrelim20::isWaitBeforeBindRequired(bool bind) const {
bool userFenceOnUnbind = false;
if (debugManager.flags.EnableUserFenceUponUnbind.get() != -1) {
userFenceOnUnbind = !!debugManager.flags.EnableUserFenceUponUnbind.get();
}
return (bind || userFenceOnUnbind);
}
void *IoctlHelperPrelim20::pciBarrierMmap() {
static constexpr uint64_t pciBarrierMmapOffset = 0x50 << 12;
return SysCalls::mmap(NULL, MemoryConstants::pageSize, PROT_WRITE, MAP_SHARED, drm.getFileDescriptor(), pciBarrierMmapOffset);
}
bool IoctlHelperPrelim20::queryHwIpVersion(EngineClassInstance &engineInfo, HardwareIpVersion &ipVersion, int &ret) {
QueryItem queryItem{};
queryItem.queryId = PRELIM_DRM_I915_QUERY_HW_IP_VERSION;
Query query{};
query.itemsPtr = reinterpret_cast<uint64_t>(&queryItem);
query.numItems = 1u;
ret = ioctl(DrmIoctl::query, &query);
if (ret != 0) {
return false;
}
if (queryItem.length != sizeof(prelim_drm_i915_query_hw_ip_version)) {
PRINT_DEBUG_STRING(debugManager.flags.PrintDebugMessages.get(), stderr, "%s\n",
"Size got from PRELIM_DRM_I915_QUERY_HW_IP_VERSION query does not match PrelimI915::prelim_drm_i915_query_hw_ip_version size");
return false;
}
prelim_drm_i915_query_hw_ip_version queryHwIpVersion{};
queryHwIpVersion.engine.engine_class = engineInfo.engineClass;
queryHwIpVersion.engine.engine_instance = engineInfo.engineInstance;
queryItem.dataPtr = reinterpret_cast<uint64_t>(&queryHwIpVersion);
ret = ioctl(DrmIoctl::query, &query);
if (ret != 0) {
return false;
}
ipVersion.architecture = queryHwIpVersion.arch;
ipVersion.release = queryHwIpVersion.release;
ipVersion.revision = queryHwIpVersion.stepping;
return true;
}
bool IoctlHelperPrelim20::initialize() {
initializeGetGpuTimeFunction();
return true;
}
void IoctlHelperPrelim20::setupIpVersion() {
auto &rootDeviceEnvironment = drm.getRootDeviceEnvironment();
auto hwInfo = rootDeviceEnvironment.getMutableHardwareInfo();
auto &productHelper = drm.getRootDeviceEnvironment().getHelper<ProductHelper>();
EngineClassInstance engineInfo = {static_cast<uint16_t>(getDrmParamValue(DrmParam::engineClassRender)), 0};
int ret = 0;
auto isPlatformQuerySupported = productHelper.isPlatformQuerySupported();
bool result = false;
if (isPlatformQuerySupported) {
result = queryHwIpVersion(engineInfo, hwInfo->ipVersion, ret);
if (result == false && ret != 0) {
int err = drm.getErrno();
PRINT_DEBUG_STRING(debugManager.flags.PrintDebugMessages.get(), stderr,
"ioctl(PRELIM_DRM_I915_QUERY_HW_IP_VERSION) failed with %d. errno=%d(%s)\n", ret, err, strerror(err));
}
}
if (result == false) {
IoctlHelper::setupIpVersion();
}
}
bool IoctlHelperPrelim20::registerResourceClasses() {
for (auto &classNameUUID : classNamesToUuid) {
auto className = classNameUUID.first;
auto uuid = classNameUUID.second;
const auto result = registerStringClassUuid(uuid, (uintptr_t)className, strnlen_s(className, 100));
if (result.retVal != 0) {
return false;
}
classHandles.push_back(result.handle);
}
return true;
}
uint32_t IoctlHelperPrelim20::registerIsaCookie(uint32_t isaHandle) {
auto uuid = generateUUID();
const auto result = registerUuid(uuid, isaHandle, 0, 0);
PRINT_DEBUGGER_INFO_LOG("PRELIM_DRM_IOCTL_I915_UUID_REGISTER: isa handle = %lu, uuid = %s, data = %p, handle = %lu, ret = %d\n", isaHandle, std::string(uuid, 36).c_str(), 0, result.handle, result.retVal);
if (result.retVal != 0) {
int err = errno;
CREATE_DEBUG_STRING(str, "ioctl(PRELIM_DRM_IOCTL_I915_UUID_REGISTER) failed with %d. errno=%d(%s)\n", result.retVal, err, strerror(err));
drm.getRootDeviceEnvironment().executionEnvironment.setErrorDescription(std::string(str.get()));
DEBUG_BREAK_IF(true);
}
return result.handle;
}
void IoctlHelperPrelim20::unregisterResource(uint32_t handle) {
PRINT_DEBUGGER_INFO_LOG("PRELIM_DRM_IOCTL_I915_UUID_UNREGISTER: handle = %lu\n", handle);
[[maybe_unused]] const auto ret = unregisterUuid(handle);
if (ret != 0) {
int err = errno;
CREATE_DEBUG_STRING(str, "ioctl(PRELIM_DRM_IOCTL_I915_UUID_UNREGISTER) failed with %d. errno=%d(%s)\n", ret, err, strerror(err));
drm.getRootDeviceEnvironment().executionEnvironment.setErrorDescription(std::string(str.get()));
DEBUG_BREAK_IF(true);
}
}
std::string IoctlHelperPrelim20::generateUUID() {
const char uuidString[] = "00000000-0000-0000-%04" SCNx64 "-%012" SCNx64;
char buffer[36 + 1] = "00000000-0000-0000-0000-000000000000";
uuid++;
UNRECOVERABLE_IF(uuid == 0xFFFFFFFFFFFFFFFF);
uint64_t parts[2] = {0, 0};
parts[0] = uuid & 0xFFFFFFFFFFFF;
parts[1] = (uuid & 0xFFFF000000000000) >> 48;
snprintf(buffer, sizeof(buffer), uuidString, parts[1], parts[0]);
return std::string(buffer, 36);
}
std::string IoctlHelperPrelim20::generateElfUUID(const void *data) {
std::string elfClassUuid = classNamesToUuid[static_cast<uint32_t>(DrmResourceClass::elf)].second;
std::string uuiD1st = elfClassUuid.substr(0, 18);
const char uuidString[] = "%s-%04" SCNx64 "-%012" SCNx64;
char buffer[36 + 1] = "00000000-0000-0000-0000-000000000000";
uint64_t parts[2] = {0, 0};
parts[0] = reinterpret_cast<uintptr_t>(data) & 0xFFFFFFFFFFFF;
parts[1] = (reinterpret_cast<uintptr_t>(data) & 0xFFFF000000000000) >> 48;
snprintf(buffer, sizeof(buffer), uuidString, uuiD1st.c_str(), parts[1], parts[0]);
return std::string(buffer, 36);
}
uint32_t IoctlHelperPrelim20::registerResource(DrmResourceClass classType, const void *data, size_t size) {
const auto classIndex = static_cast<uint32_t>(classType);
if (classHandles.size() <= classIndex) {
return 0;
}
std::string uuid;
if (classType == NEO::DrmResourceClass::elf) {
uuid = generateElfUUID(data);
} else {
uuid = generateUUID();
}
const auto uuidClass = classHandles[classIndex];
const auto ptr = size > 0 ? (uintptr_t)data : 0;
const auto result = registerUuid(uuid, uuidClass, ptr, size);
PRINT_DEBUGGER_INFO_LOG("PRELIM_DRM_IOCTL_I915_UUID_REGISTER: classType = %d, uuid = %s, data = %p, handle = %lu, ret = %d\n", (int)classType, std::string(uuid, 36).c_str(), ptr, result.handle, result.retVal);
if (result.retVal != 0) {
int err = errno;
CREATE_DEBUG_STRING(str, "ioctl(PRELIM_DRM_IOCTL_I915_UUID_REGISTER) failed with %d. errno=%d(%s)\n", result.retVal, err, strerror(err));
drm.getRootDeviceEnvironment().executionEnvironment.setErrorDescription(std::string(str.get()));
DEBUG_BREAK_IF(true);
}
return result.handle;
}
uint32_t IoctlHelperPrelim20::notifyFirstCommandQueueCreated(const void *data, size_t size) {
const auto result = registerStringClassUuid(uuidL0CommandQueueHash, (uintptr_t)data, size);
DEBUG_BREAK_IF(result.retVal);
return result.handle;
}
void IoctlHelperPrelim20::notifyLastCommandQueueDestroyed(uint32_t handle) {
unregisterResource(handle);
}
int IoctlHelperPrelim20::getEuDebugSysFsEnable() {
char enabledEuDebug = '0';
std::string sysFsPciPath = drm.getSysFsPciPath();
std::string euDebugPath = sysFsPciPath + "/prelim_enable_eu_debug";
FILE *fileDescriptor = IoFunctions::fopenPtr(euDebugPath.c_str(), "r");
if (fileDescriptor) {
[[maybe_unused]] auto bytesRead = IoFunctions::freadPtr(&enabledEuDebug, 1, 1, fileDescriptor);
IoFunctions::fclosePtr(fileDescriptor);
}
return enabledEuDebug - '0';
}
bool IoctlHelperPrelim20::validPageFault(uint16_t flags) {
if ((flags & I915_RESET_STATS_FAULT_VALID) != 0) {
return true;
}
return false;
}
uint32_t IoctlHelperPrelim20::getStatusForResetStats(bool banned) {
uint32_t retVal = 0u;
if (banned) {
retVal |= I915_RESET_STATS_BANNED;
}
return retVal;
}
void IoctlHelperPrelim20::registerBOBindHandle(Drm *drm, DrmAllocation *drmAllocation) {
DrmResourceClass resourceClass = DrmResourceClass::maxSize;
switch (drmAllocation->getAllocationType()) {
case AllocationType::debugContextSaveArea:
resourceClass = DrmResourceClass::contextSaveArea;
break;
case AllocationType::debugSbaTrackingBuffer:
resourceClass = DrmResourceClass::sbaTrackingBuffer;
break;
case AllocationType::kernelIsa:
resourceClass = DrmResourceClass::isa;
break;
case AllocationType::debugModuleArea:
resourceClass = DrmResourceClass::moduleHeapDebugArea;
break;
default:
break;
}
if (resourceClass != DrmResourceClass::maxSize) {
auto handle = 0;
if (resourceClass == DrmResourceClass::isa) {
auto deviceBitfiled = static_cast<uint32_t>(drmAllocation->storageInfo.subDeviceBitfield.to_ulong());
handle = drm->registerResource(resourceClass, &deviceBitfiled, sizeof(deviceBitfiled));
} else {
uint64_t gpuAddress = drmAllocation->getGpuAddress();
handle = drm->registerResource(resourceClass, &gpuAddress, sizeof(gpuAddress));
}
drmAllocation->addRegisteredBoBindHandle(handle);
auto &bos = drmAllocation->getBOs();
uint32_t boIndex = 0u;
for (auto bo : bos) {
if (bo) {
bo->addBindExtHandle(handle);
bo->markForCapture();
if (resourceClass == DrmResourceClass::isa && drmAllocation->storageInfo.tileInstanced == true) {
auto cookieHandle = drm->registerIsaCookie(handle);
bo->addBindExtHandle(cookieHandle);
drmAllocation->addRegisteredBoBindHandle(cookieHandle);
}
auto storageInfo = drmAllocation->storageInfo;
if (resourceClass == DrmResourceClass::sbaTrackingBuffer && drmAllocation->getOsContext()) {
auto deviceIndex = [=]() -> uint32_t {
if (storageInfo.tileInstanced == true) {
return boIndex;
}
auto deviceBitfield = storageInfo.subDeviceBitfield;
return deviceBitfield.any() ? static_cast<uint32_t>(Math::log2(static_cast<uint32_t>(deviceBitfield.to_ulong()))) : 0u;
}();
auto contextId = drmAllocation->getOsContext()->getOfflineDumpContextId(deviceIndex);
auto externalHandle = drm->registerResource(resourceClass, &contextId, sizeof(uint64_t));
bo->addBindExtHandle(externalHandle);
drmAllocation->addRegisteredBoBindHandle(externalHandle);
}
bo->requireImmediateBinding(true);
}
boIndex++;
}
}
}
static_assert(sizeof(MemoryClassInstance) == sizeof(prelim_drm_i915_gem_memory_class_instance));
static_assert(offsetof(MemoryClassInstance, memoryClass) == offsetof(prelim_drm_i915_gem_memory_class_instance, memory_class));
static_assert(offsetof(MemoryClassInstance, memoryInstance) == offsetof(prelim_drm_i915_gem_memory_class_instance, memory_instance));
static_assert(sizeof(ResetStatsFault) == sizeof(prelim_drm_i915_reset_stats::fault));
} // namespace NEO