2017-12-21 07:45:38 +08:00
|
|
|
/*
|
2020-01-02 20:20:18 +08:00
|
|
|
* Copyright (C) 2017-2020 Intel Corporation
|
2017-12-21 07:45:38 +08:00
|
|
|
*
|
2018-09-18 15:11:08 +08:00
|
|
|
* SPDX-License-Identifier: MIT
|
2017-12-21 07:45:38 +08:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "drm_neo.h"
|
2019-02-27 18:39:32 +08:00
|
|
|
|
2020-02-24 01:46:50 +08:00
|
|
|
#include "debug_settings/debug_settings_manager.h"
|
|
|
|
#include "helpers/debug_helpers.h"
|
|
|
|
#include "helpers/hw_info.h"
|
|
|
|
#include "memory_manager/memory_constants.h"
|
|
|
|
#include "os_interface/linux/hw_device_id.h"
|
|
|
|
#include "os_interface/linux/os_inc.h"
|
|
|
|
#include "os_interface/linux/sys_calls.h"
|
|
|
|
#include "os_interface/os_interface.h"
|
|
|
|
#include "utilities/directory.h"
|
2019-02-27 18:39:32 +08:00
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstring>
|
|
|
|
#include <fstream>
|
2020-02-07 21:32:02 +08:00
|
|
|
#include <linux/limits.h>
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2019-03-26 18:59:46 +08:00
|
|
|
namespace NEO {
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
const char *Drm::sysFsDefaultGpuPath = "/drm/card0";
|
|
|
|
const char *Drm::maxGpuFrequencyFile = "/gt_max_freq_mhz";
|
|
|
|
const char *Drm::configFileName = "/config";
|
|
|
|
|
2020-01-31 23:10:03 +08:00
|
|
|
namespace IoctlHelper {
|
|
|
|
constexpr const char *getIoctlParamString(int param) {
|
|
|
|
switch (param) {
|
|
|
|
case I915_PARAM_CHIPSET_ID:
|
|
|
|
return "I915_PARAM_CHIPSET_ID";
|
|
|
|
case I915_PARAM_REVISION:
|
|
|
|
return "I915_PARAM_REVISION";
|
|
|
|
case I915_PARAM_HAS_EXEC_SOFTPIN:
|
|
|
|
return "I915_PARAM_HAS_EXEC_SOFTPIN";
|
|
|
|
case I915_PARAM_HAS_POOLED_EU:
|
|
|
|
return "I915_PARAM_HAS_POOLED_EU";
|
|
|
|
case I915_PARAM_HAS_SCHEDULER:
|
|
|
|
return "I915_PARAM_HAS_SCHEDULER";
|
|
|
|
case I915_PARAM_EU_TOTAL:
|
|
|
|
return "I915_PARAM_EU_TOTAL";
|
|
|
|
case I915_PARAM_SUBSLICE_TOTAL:
|
|
|
|
return "I915_PARAM_SUBSLICE_TOTAL";
|
|
|
|
case I915_PARAM_MIN_EU_IN_POOL:
|
|
|
|
return "I915_PARAM_MIN_EU_IN_POOL";
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return "UNKNOWN";
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace IoctlHelper
|
|
|
|
|
2017-12-21 07:45:38 +08:00
|
|
|
int Drm::ioctl(unsigned long request, void *arg) {
|
|
|
|
int ret;
|
|
|
|
SYSTEM_ENTER();
|
|
|
|
do {
|
2020-02-13 20:26:40 +08:00
|
|
|
ret = SysCalls::ioctl(getFileDescriptor(), request, arg);
|
2017-12-21 07:45:38 +08:00
|
|
|
} while (ret == -1 && (errno == EINTR || errno == EAGAIN));
|
|
|
|
SYSTEM_LEAVE(request);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2018-03-12 19:03:20 +08:00
|
|
|
int Drm::getParamIoctl(int param, int *dstValue) {
|
|
|
|
drm_i915_getparam_t getParam = {};
|
|
|
|
getParam.param = param;
|
|
|
|
getParam.value = dstValue;
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2020-01-31 23:10:03 +08:00
|
|
|
int retVal = ioctl(DRM_IOCTL_I915_GETPARAM, &getParam);
|
|
|
|
|
|
|
|
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stdout,
|
|
|
|
"\nDRM_IOCTL_I915_GETPARAM: param: %s, output value: %d, retCode: %d\n",
|
|
|
|
IoctlHelper::getIoctlParamString(param), *getParam.value, retVal);
|
|
|
|
|
|
|
|
return retVal;
|
2018-03-12 19:03:20 +08:00
|
|
|
}
|
2017-12-21 07:45:38 +08:00
|
|
|
|
2018-03-12 19:03:20 +08:00
|
|
|
int Drm::getDeviceID(int &devId) {
|
|
|
|
return getParamIoctl(I915_PARAM_CHIPSET_ID, &devId);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::getDeviceRevID(int &revId) {
|
2018-03-12 19:03:20 +08:00
|
|
|
return getParamIoctl(I915_PARAM_REVISION, &revId);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::getExecSoftPin(int &execSoftPin) {
|
2018-03-12 19:03:20 +08:00
|
|
|
return getParamIoctl(I915_PARAM_HAS_EXEC_SOFTPIN, &execSoftPin);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::enableTurboBoost() {
|
2018-03-20 17:49:09 +08:00
|
|
|
drm_i915_gem_context_param contextParam = {};
|
2017-12-21 07:45:38 +08:00
|
|
|
|
|
|
|
contextParam.param = I915_CONTEXT_PRIVATE_PARAM_BOOST;
|
|
|
|
contextParam.value = 1;
|
2018-03-20 17:49:09 +08:00
|
|
|
return ioctl(DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &contextParam);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::getEnabledPooledEu(int &enabled) {
|
2018-03-12 19:03:20 +08:00
|
|
|
return getParamIoctl(I915_PARAM_HAS_POOLED_EU, &enabled);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::getMaxGpuFrequency(int &maxGpuFrequency) {
|
|
|
|
maxGpuFrequency = 0;
|
|
|
|
int deviceID = 0;
|
|
|
|
int ret = getDeviceID(deviceID);
|
|
|
|
if (ret != 0) {
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
std::string clockSysFsPath = getSysFsPciPath(deviceID);
|
|
|
|
|
|
|
|
if (clockSysFsPath.size() == 0) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
clockSysFsPath += sysFsDefaultGpuPath;
|
|
|
|
clockSysFsPath += maxGpuFrequencyFile;
|
|
|
|
|
|
|
|
std::ifstream ifs(clockSysFsPath.c_str(), std::ifstream::in);
|
|
|
|
if (ifs.fail()) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
ifs >> maxGpuFrequency;
|
|
|
|
ifs.close();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string Drm::getSysFsPciPath(int deviceID) {
|
|
|
|
std::string nullPath;
|
|
|
|
std::string sysFsPciDirectory = Os::sysFsPciPath;
|
|
|
|
std::vector<std::string> files = Directory::getFiles(sysFsPciDirectory);
|
|
|
|
|
|
|
|
for (std::vector<std::string>::iterator file = files.begin(); file != files.end(); ++file) {
|
2018-03-20 17:49:09 +08:00
|
|
|
PCIConfig config = {};
|
2017-12-21 07:45:38 +08:00
|
|
|
std::string configPath = *file + configFileName;
|
|
|
|
std::string sysfsPath = *file;
|
|
|
|
std::ifstream configFile(configPath, std::ifstream::binary);
|
|
|
|
if (configFile.is_open()) {
|
|
|
|
configFile.read(reinterpret_cast<char *>(&config), sizeof(config));
|
|
|
|
|
|
|
|
if (!configFile.good() || (config.DeviceID != deviceID)) {
|
|
|
|
configFile.close();
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
return sysfsPath;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullPath;
|
|
|
|
}
|
|
|
|
|
2019-12-17 22:17:52 +08:00
|
|
|
int Drm::queryGttSize(uint64_t >tSizeOutput) {
|
2019-04-23 21:42:33 +08:00
|
|
|
drm_i915_gem_context_param contextParam = {0};
|
|
|
|
contextParam.param = I915_CONTEXT_PARAM_GTT_SIZE;
|
|
|
|
|
2019-12-17 22:17:52 +08:00
|
|
|
int ret = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &contextParam);
|
2019-04-23 21:42:33 +08:00
|
|
|
if (ret == 0) {
|
2019-12-17 22:17:52 +08:00
|
|
|
gttSizeOutput = contextParam.value;
|
2019-04-23 21:42:33 +08:00
|
|
|
}
|
2019-12-17 22:17:52 +08:00
|
|
|
|
|
|
|
return ret;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2018-12-07 22:03:23 +08:00
|
|
|
void Drm::checkPreemptionSupport() {
|
2017-12-21 07:45:38 +08:00
|
|
|
int value = 0;
|
2019-03-22 13:21:52 +08:00
|
|
|
auto ret = getParamIoctl(I915_PARAM_HAS_SCHEDULER, &value);
|
|
|
|
preemptionSupported = ((0 == ret) && (value & I915_SCHEDULER_CAP_PREEMPTION));
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2019-08-21 18:50:47 +08:00
|
|
|
void Drm::checkQueueSliceSupport() {
|
|
|
|
sliceCountChangeSupported = getQueueSliceCount(&sseu) == 0 ? true : false;
|
|
|
|
}
|
|
|
|
|
2018-12-11 15:21:56 +08:00
|
|
|
void Drm::setLowPriorityContextParam(uint32_t drmContextId) {
|
2018-12-07 22:03:23 +08:00
|
|
|
drm_i915_gem_context_param gcp = {};
|
2018-12-11 15:21:56 +08:00
|
|
|
gcp.ctx_id = drmContextId;
|
2017-12-21 07:45:38 +08:00
|
|
|
gcp.param = I915_CONTEXT_PARAM_PRIORITY;
|
|
|
|
gcp.value = -1023;
|
|
|
|
|
2018-12-11 15:21:56 +08:00
|
|
|
auto retVal = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &gcp);
|
|
|
|
UNRECOVERABLE_IF(retVal != 0);
|
|
|
|
}
|
|
|
|
|
2019-08-21 18:50:47 +08:00
|
|
|
int Drm::getQueueSliceCount(drm_i915_gem_context_param_sseu *sseu) {
|
|
|
|
drm_i915_gem_context_param contextParam = {};
|
|
|
|
contextParam.param = I915_CONTEXT_PARAM_SSEU;
|
|
|
|
sseu->engine.engine_class = I915_ENGINE_CLASS_RENDER;
|
|
|
|
sseu->engine.engine_instance = I915_EXEC_DEFAULT;
|
|
|
|
contextParam.value = reinterpret_cast<uint64_t>(sseu);
|
|
|
|
contextParam.size = sizeof(struct drm_i915_gem_context_param_sseu);
|
|
|
|
|
|
|
|
return ioctl(DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &contextParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint64_t Drm::getSliceMask(uint64_t sliceCount) {
|
2019-11-28 01:00:52 +08:00
|
|
|
return maxNBitValue(sliceCount);
|
2019-08-21 18:50:47 +08:00
|
|
|
}
|
|
|
|
bool Drm::setQueueSliceCount(uint64_t sliceCount) {
|
|
|
|
if (sliceCountChangeSupported) {
|
|
|
|
drm_i915_gem_context_param contextParam = {};
|
|
|
|
sseu.slice_mask = getSliceMask(sliceCount);
|
|
|
|
|
|
|
|
contextParam.param = I915_CONTEXT_PARAM_SSEU;
|
|
|
|
contextParam.ctx_id = 0;
|
|
|
|
contextParam.value = reinterpret_cast<uint64_t>(&sseu);
|
|
|
|
contextParam.size = sizeof(struct drm_i915_gem_context_param_sseu);
|
|
|
|
int retVal = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &contextParam);
|
|
|
|
if (retVal == 0) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-02-11 00:05:32 +08:00
|
|
|
void Drm::checkNonPersistentContextsSupport() {
|
2019-12-19 02:38:22 +08:00
|
|
|
drm_i915_gem_context_param contextParam = {};
|
|
|
|
contextParam.param = I915_CONTEXT_PARAM_PERSISTENCE;
|
2020-02-11 00:05:32 +08:00
|
|
|
|
|
|
|
auto retVal = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &contextParam);
|
|
|
|
if (retVal == 0 && contextParam.value == 1) {
|
|
|
|
nonPersistentContextsSupported = true;
|
|
|
|
} else {
|
|
|
|
nonPersistentContextsSupported = false;
|
|
|
|
}
|
2019-12-19 02:38:22 +08:00
|
|
|
}
|
|
|
|
|
2019-12-24 19:20:23 +08:00
|
|
|
void Drm::setNonPersistentContext(uint32_t drmContextId) {
|
2019-12-19 02:38:22 +08:00
|
|
|
drm_i915_gem_context_param contextParam = {};
|
|
|
|
contextParam.ctx_id = drmContextId;
|
|
|
|
contextParam.param = I915_CONTEXT_PARAM_PERSISTENCE;
|
|
|
|
|
2020-02-11 00:05:32 +08:00
|
|
|
ioctl(DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &contextParam);
|
2019-12-19 02:38:22 +08:00
|
|
|
}
|
|
|
|
|
2018-12-11 15:21:56 +08:00
|
|
|
uint32_t Drm::createDrmContext() {
|
|
|
|
drm_i915_gem_context_create gcc = {};
|
|
|
|
auto retVal = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &gcc);
|
2018-12-07 22:03:23 +08:00
|
|
|
UNRECOVERABLE_IF(retVal != 0);
|
2018-12-11 15:21:56 +08:00
|
|
|
|
|
|
|
return gcc.ctx_id;
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2018-12-11 15:21:56 +08:00
|
|
|
void Drm::destroyDrmContext(uint32_t drmContextId) {
|
2018-03-20 17:49:09 +08:00
|
|
|
drm_i915_gem_context_destroy destroy = {};
|
2018-12-11 15:21:56 +08:00
|
|
|
destroy.ctx_id = drmContextId;
|
2018-12-07 22:03:23 +08:00
|
|
|
auto retVal = ioctl(DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &destroy);
|
|
|
|
UNRECOVERABLE_IF(retVal != 0);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::getEuTotal(int &euTotal) {
|
2019-07-23 17:45:10 +08:00
|
|
|
return getParamIoctl(I915_PARAM_EU_TOTAL, &euTotal);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::getSubsliceTotal(int &subsliceTotal) {
|
2018-03-12 19:03:20 +08:00
|
|
|
return getParamIoctl(I915_PARAM_SUBSLICE_TOTAL, &subsliceTotal);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
int Drm::getMinEuInPool(int &minEUinPool) {
|
2018-03-12 19:03:20 +08:00
|
|
|
return getParamIoctl(I915_PARAM_MIN_EU_IN_POOL, &minEUinPool);
|
2017-12-21 07:45:38 +08:00
|
|
|
}
|
|
|
|
|
2018-02-28 19:09:48 +08:00
|
|
|
int Drm::getErrno() {
|
|
|
|
return errno;
|
|
|
|
}
|
|
|
|
|
2019-10-18 16:15:09 +08:00
|
|
|
int Drm::setupHardwareInfo(DeviceDescriptor *device, bool setupFeatureTableAndWorkaroundTable) {
|
|
|
|
HardwareInfo *hwInfo = const_cast<HardwareInfo *>(device->pHwInfo);
|
|
|
|
int ret;
|
|
|
|
int euTotal;
|
|
|
|
int subsliceTotal;
|
|
|
|
|
|
|
|
ret = getEuTotal(euTotal);
|
|
|
|
if (ret != 0) {
|
|
|
|
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s", "FATAL: Cannot query EU total parameter!\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = getSubsliceTotal(subsliceTotal);
|
|
|
|
if (ret != 0) {
|
|
|
|
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s", "FATAL: Cannot query subslice total parameter!\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
hwInfo->gtSystemInfo.EUCount = static_cast<uint32_t>(euTotal);
|
|
|
|
hwInfo->gtSystemInfo.SubSliceCount = static_cast<uint32_t>(subsliceTotal);
|
|
|
|
device->setupHardwareInfo(hwInfo, setupFeatureTableAndWorkaroundTable);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-02-17 23:14:22 +08:00
|
|
|
std::vector<std::unique_ptr<HwDeviceId>> OSInterface::discoverDevices() {
|
|
|
|
std::vector<std::unique_ptr<HwDeviceId>> hwDeviceIds;
|
2020-02-07 21:32:02 +08:00
|
|
|
char fullPath[PATH_MAX];
|
2020-02-17 23:14:22 +08:00
|
|
|
size_t numRootDevices = 1u;
|
|
|
|
if (DebugManager.flags.CreateMultipleRootDevices.get()) {
|
|
|
|
numRootDevices = DebugManager.flags.CreateMultipleRootDevices.get();
|
|
|
|
}
|
2020-02-07 21:32:02 +08:00
|
|
|
if (DebugManager.flags.ForceDeviceId.get() != "unk") {
|
|
|
|
snprintf(fullPath, PATH_MAX, "/dev/dri/by-path/pci-0000:%s-render", DebugManager.flags.ForceDeviceId.get().c_str());
|
|
|
|
int fileDescriptor = SysCalls::open(fullPath, O_RDWR);
|
|
|
|
if (fileDescriptor >= 0) {
|
2020-02-13 20:26:40 +08:00
|
|
|
if (Drm::isi915Version(fileDescriptor)) {
|
2020-02-17 23:14:22 +08:00
|
|
|
while (hwDeviceIds.size() < numRootDevices) {
|
|
|
|
hwDeviceIds.push_back(std::make_unique<HwDeviceId>(fileDescriptor));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SysCalls::close(fileDescriptor);
|
2020-02-07 21:32:02 +08:00
|
|
|
}
|
|
|
|
}
|
2020-02-17 23:14:22 +08:00
|
|
|
return hwDeviceIds;
|
2020-02-07 21:32:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const char *pathPrefix = "/dev/dri/renderD";
|
|
|
|
const unsigned int maxDrmDevices = 64;
|
|
|
|
unsigned int startNum = 128;
|
|
|
|
|
|
|
|
for (unsigned int i = 0; i < maxDrmDevices; i++) {
|
|
|
|
snprintf(fullPath, PATH_MAX, "%s%u", pathPrefix, i + startNum);
|
|
|
|
int fileDescriptor = SysCalls::open(fullPath, O_RDWR);
|
|
|
|
if (fileDescriptor >= 0) {
|
2020-02-13 20:26:40 +08:00
|
|
|
if (Drm::isi915Version(fileDescriptor)) {
|
2020-02-17 23:14:22 +08:00
|
|
|
hwDeviceIds.push_back(std::make_unique<HwDeviceId>(fileDescriptor));
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
SysCalls::close(fileDescriptor);
|
2020-02-07 21:32:02 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-02-17 23:14:22 +08:00
|
|
|
if (hwDeviceIds.empty()) {
|
|
|
|
return hwDeviceIds;
|
|
|
|
}
|
|
|
|
while (hwDeviceIds.size() < numRootDevices) {
|
|
|
|
hwDeviceIds.push_back(std::make_unique<HwDeviceId>(hwDeviceIds[0]->getFileDescriptor()));
|
|
|
|
}
|
|
|
|
return hwDeviceIds;
|
2020-02-07 21:32:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Drm::isi915Version(int fileDescriptor) {
|
|
|
|
drm_version_t version = {};
|
|
|
|
char name[5] = {};
|
|
|
|
version.name = name;
|
|
|
|
version.name_len = 5;
|
|
|
|
|
2020-02-13 20:26:40 +08:00
|
|
|
int ret = SysCalls::ioctl(fileDescriptor, DRM_IOCTL_VERSION, &version);
|
2020-02-07 21:32:02 +08:00
|
|
|
if (ret) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
name[4] = '\0';
|
|
|
|
return strcmp(name, "i915") == 0;
|
|
|
|
}
|
|
|
|
|
2020-02-13 22:04:21 +08:00
|
|
|
Drm::~Drm() = default;
|
|
|
|
|
2019-03-26 18:59:46 +08:00
|
|
|
} // namespace NEO
|