243 lines
9.3 KiB
C++
243 lines
9.3 KiB
C++
/*
|
|
* Copyright (C) 2021-2022 Intel Corporation
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*
|
|
*/
|
|
|
|
#include "shared/source/debug_settings/debug_settings_manager.h"
|
|
#include "shared/source/helpers/debug_helpers.h"
|
|
#include "shared/source/os_interface/linux/cache_info.h"
|
|
#include "shared/source/os_interface/linux/ioctl_helper.h"
|
|
|
|
#include "third_party/uapi/prelim/drm/i915_drm.h"
|
|
|
|
#include <algorithm>
|
|
#include <cerrno>
|
|
#include <cstring>
|
|
#include <sys/ioctl.h>
|
|
|
|
namespace NEO {
|
|
|
|
uint32_t IoctlHelperPrelim20::createGemExt(Drm *drm, const std::vector<MemoryClassInstance> &memClassInstances, size_t allocSize, uint32_t &handle) {
|
|
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 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);
|
|
}
|
|
printDebugString(DebugManager.flags.PrintBOCreateDestroyResult.get(), stdout, "%s", " }\n");
|
|
}
|
|
|
|
auto ret = IoctlHelper::ioctl(drm, PRELIM_DRM_IOCTL_I915_GEM_CREATE_EXT, &createExt);
|
|
|
|
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;
|
|
}
|
|
|
|
std::vector<MemoryRegion> IoctlHelperPrelim20::translateToMemoryRegions(const std::vector<uint8_t> ®ionInfo) {
|
|
auto *data = reinterpret_cast<const prelim_drm_i915_query_memory_regions *>(regionInfo.data());
|
|
auto memRegions = std::vector<MemoryRegion>(data->num_regions);
|
|
for (uint32_t i = 0; i < data->num_regions; i++) {
|
|
memRegions[i].probedSize = data->regions[i].probed_size;
|
|
memRegions[i].unallocatedSize = data->regions[i].unallocated_size;
|
|
memRegions[i].region.memoryClass = data->regions[i].region.memory_class;
|
|
memRegions[i].region.memoryInstance = data->regions[i].region.memory_instance;
|
|
}
|
|
return memRegions;
|
|
}
|
|
|
|
CacheRegion IoctlHelperPrelim20::closAlloc(Drm *drm) {
|
|
struct prelim_drm_i915_gem_clos_reserve clos = {};
|
|
|
|
int ret = IoctlHelper::ioctl(drm, PRELIM_DRM_IOCTL_I915_GEM_CLOS_RESERVE, &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(Drm *drm, 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(drm, PRELIM_DRM_IOCTL_I915_GEM_CACHE_RESERVE, &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(Drm *drm, CacheRegion closIndex) {
|
|
struct prelim_drm_i915_gem_clos_free clos = {};
|
|
|
|
clos.clos_index = static_cast<uint16_t>(closIndex);
|
|
|
|
int ret = IoctlHelper::ioctl(drm, PRELIM_DRM_IOCTL_I915_GEM_CLOS_FREE, &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(Drm *drm, uint32_t ctxId, uint64_t address,
|
|
uint64_t value, uint32_t dataWidth, int64_t timeout, uint16_t flags) {
|
|
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(drm, PRELIM_DRM_IOCTL_I915_GEM_WAIT_USER_FENCE, &wait);
|
|
}
|
|
|
|
uint32_t IoctlHelperPrelim20::getHwConfigIoctlVal() {
|
|
return PRELIM_DRM_I915_QUERY_HWCONFIG_TABLE;
|
|
}
|
|
|
|
uint32_t IoctlHelperPrelim20::getAtomicAdvise(bool isNonAtomic) {
|
|
return isNonAtomic ? PRELIM_I915_VM_ADVISE_ATOMIC_NONE : PRELIM_I915_VM_ADVISE_ATOMIC_SYSTEM;
|
|
}
|
|
|
|
uint32_t IoctlHelperPrelim20::getPreferredLocationAdvise() {
|
|
return PRELIM_I915_VM_ADVISE_PREFERRED_LOCATION;
|
|
}
|
|
|
|
bool IoctlHelperPrelim20::setVmBoAdvise(Drm *drm, 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(drm, PRELIM_DRM_IOCTL_I915_GEM_VM_ADVISE, &vmAdvise);
|
|
if (ret != 0) {
|
|
int err = errno;
|
|
PRINT_DEBUG_STRING(DebugManager.flags.PrintDebugMessages.get(), stderr, "ioctl(PRELIM_DRM_I915_GEM_VM_ADVISE) failed with %d. errno=%d(%s)\n", ret, err, strerror(err));
|
|
DEBUG_BREAK_IF(true);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
uint32_t IoctlHelperPrelim20::getDirectSubmissionFlag() {
|
|
return PRELIM_I915_CONTEXT_CREATE_FLAGS_ULLS;
|
|
}
|
|
|
|
int32_t IoctlHelperPrelim20::getMemRegionsIoctlVal() {
|
|
return PRELIM_DRM_I915_QUERY_MEMORY_REGIONS;
|
|
}
|
|
|
|
int32_t IoctlHelperPrelim20::getEngineInfoIoctlVal() {
|
|
return PRELIM_DRM_I915_QUERY_ENGINE_INFO;
|
|
}
|
|
|
|
std::vector<EngineCapabilities> IoctlHelperPrelim20::translateToEngineCaps(const std::vector<uint8_t> &data) {
|
|
auto engineInfo = reinterpret_cast<const prelim_drm_i915_query_engine_info *>(data.data());
|
|
std::vector<EngineCapabilities> engines;
|
|
engines.reserve(engineInfo->num_engines);
|
|
for (uint32_t i = 0; i < engineInfo->num_engines; i++) {
|
|
EngineCapabilities engine{};
|
|
engine.capabilities = engineInfo->engines[i].capabilities;
|
|
engine.engine.engineClass = engineInfo->engines[i].engine.engine_class;
|
|
engine.engine.engineInstance = engineInfo->engines[i].engine.engine_instance;
|
|
engines.push_back(engine);
|
|
}
|
|
return engines;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
uint32_t IoctlHelperPrelim20::queryDistances(Drm *drm, std::vector<drm_i915_query_item> &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].query_id = PRELIM_DRM_I915_QUERY_DISTANCE_INFO;
|
|
queryItems[i].length = sizeof(prelim_drm_i915_query_distance_info);
|
|
queryItems[i].flags = 0u;
|
|
queryItems[i].data_ptr = reinterpret_cast<__u64>(&i915Distances[i]);
|
|
}
|
|
|
|
drm_i915_query query{};
|
|
query.items_ptr = reinterpret_cast<__u64>(queryItems.data());
|
|
query.num_items = static_cast<uint32_t>(queryItems.size());
|
|
auto ret = IoctlHelper::ioctl(drm, DRM_IOCTL_I915_QUERY, &query);
|
|
for (auto i = 0u; i < i915Distances.size(); i++) {
|
|
distanceInfos[i].distance = i915Distances[i].distance;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int32_t IoctlHelperPrelim20::getComputeEngineClass() {
|
|
return PRELIM_I915_ENGINE_CLASS_COMPUTE;
|
|
}
|
|
|
|
} // namespace NEO
|