2017-12-21 00:45:38 +01:00
|
|
|
/*
|
2021-01-25 20:43:48 +00:00
|
|
|
* Copyright (C) 2017-2021 Intel Corporation
|
2017-12-21 00:45:38 +01:00
|
|
|
*
|
2018-09-18 09:11:08 +02:00
|
|
|
* SPDX-License-Identifier: MIT
|
2017-12-21 00:45:38 +01:00
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2020-02-23 22:44:01 +01:00
|
|
|
#include "shared/source/execution_environment/execution_environment.h"
|
2020-07-07 09:34:31 +02:00
|
|
|
#include "shared/source/execution_environment/root_device_environment.h"
|
2020-04-02 11:28:38 +02:00
|
|
|
#include "shared/source/helpers/constants.h"
|
2020-07-07 09:34:31 +02:00
|
|
|
#include "shared/source/helpers/hw_helper.h"
|
2020-09-17 13:27:32 +02:00
|
|
|
#include "shared/source/helpers/string.h"
|
2020-02-23 22:44:01 +01:00
|
|
|
#include "shared/source/os_interface/linux/drm_neo.h"
|
2020-02-24 10:22:30 +01:00
|
|
|
|
2020-02-22 22:50:57 +01:00
|
|
|
#include "opencl/source/platform/platform.h"
|
2020-07-07 09:34:31 +02:00
|
|
|
#include "opencl/test/unit_test/linux/mock_os_layer.h"
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2019-02-27 11:39:32 +01:00
|
|
|
#include "drm/i915_drm.h"
|
2020-08-24 13:08:59 -04:00
|
|
|
#include "gtest/gtest.h"
|
2017-12-21 00:45:38 +01:00
|
|
|
|
|
|
|
|
#include <cstdio>
|
|
|
|
|
#include <fstream>
|
2019-08-21 03:50:47 -07:00
|
|
|
#include <limits.h>
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2019-03-26 11:59:46 +01:00
|
|
|
using namespace NEO;
|
2017-12-21 00:45:38 +01:00
|
|
|
|
|
|
|
|
// Mock DRM class that responds to DRM_IOCTL_I915_GETPARAMs
|
2018-03-30 09:00:26 +02:00
|
|
|
class DrmMock : public Drm {
|
2017-12-21 00:45:38 +01:00
|
|
|
public:
|
2020-11-19 20:43:01 +00:00
|
|
|
using Drm::bindAvailable;
|
2021-01-29 22:23:06 +00:00
|
|
|
using Drm::cacheInfo;
|
2019-08-21 03:50:47 -07:00
|
|
|
using Drm::checkQueueSliceSupport;
|
2020-09-14 13:28:47 +02:00
|
|
|
using Drm::classHandles;
|
2021-01-25 20:43:48 +00:00
|
|
|
using Drm::contextDebugSupported;
|
2019-11-08 18:49:54 +01:00
|
|
|
using Drm::engineInfo;
|
2020-12-11 13:28:22 -08:00
|
|
|
using Drm::generateElfUUID;
|
2020-09-08 17:33:33 +02:00
|
|
|
using Drm::generateUUID;
|
2019-08-21 03:50:47 -07:00
|
|
|
using Drm::getQueueSliceCount;
|
2019-03-19 13:53:55 +01:00
|
|
|
using Drm::memoryInfo;
|
2020-02-10 08:05:32 -08:00
|
|
|
using Drm::nonPersistentContextsSupported;
|
2018-12-11 08:21:56 +01:00
|
|
|
using Drm::preemptionSupported;
|
2019-04-30 13:09:49 +02:00
|
|
|
using Drm::query;
|
2020-07-15 08:07:53 +02:00
|
|
|
using Drm::requirePerContextVM;
|
2019-08-21 03:50:47 -07:00
|
|
|
using Drm::sliceCountChangeSupported;
|
2020-11-24 16:00:33 +01:00
|
|
|
using Drm::systemInfo;
|
2020-07-07 09:34:31 +02:00
|
|
|
using Drm::virtualMemoryIds;
|
2018-12-11 08:21:56 +01:00
|
|
|
|
2020-07-07 09:34:31 +02:00
|
|
|
DrmMock(int fd, RootDeviceEnvironment &rootDeviceEnvironment) : Drm(std::make_unique<HwDeviceId>(fd, ""), rootDeviceEnvironment) {
|
2019-08-21 03:50:47 -07:00
|
|
|
sliceCountChangeSupported = true;
|
2020-11-23 14:31:20 +00:00
|
|
|
|
|
|
|
|
if (rootDeviceEnvironment.executionEnvironment.isDebuggingEnabled()) {
|
|
|
|
|
setPerContextVMRequired(true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!isPerContextVMRequired()) {
|
2020-07-15 08:07:53 +02:00
|
|
|
createVirtualMemoryAddressSpace(HwHelper::getSubDevicesCount(rootDeviceEnvironment.getHardwareInfo()));
|
|
|
|
|
}
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
2020-07-07 09:34:31 +02:00
|
|
|
DrmMock(RootDeviceEnvironment &rootDeviceEnvironment) : DrmMock(mockFd, rootDeviceEnvironment) {}
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2019-07-23 11:45:10 +02:00
|
|
|
int ioctl(unsigned long request, void *arg) override;
|
2020-09-10 12:36:44 +02:00
|
|
|
int getErrno() override {
|
|
|
|
|
if (baseErrno) {
|
|
|
|
|
return Drm::getErrno();
|
|
|
|
|
}
|
|
|
|
|
return errnoRetVal;
|
|
|
|
|
}
|
2017-12-21 00:45:38 +01:00
|
|
|
|
|
|
|
|
void writeConfigFile(const char *name, int deviceID) {
|
|
|
|
|
std::ofstream tempfile(name, std::ios::binary);
|
|
|
|
|
if (tempfile.is_open()) {
|
|
|
|
|
PCIConfig config;
|
|
|
|
|
config.DeviceID = deviceID;
|
|
|
|
|
tempfile.write(reinterpret_cast<char *>(&config), sizeof(config));
|
|
|
|
|
tempfile.close();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void deleteConfigFile(const char *name) {
|
|
|
|
|
std::ofstream tempfile(name);
|
|
|
|
|
if (tempfile.is_open()) {
|
|
|
|
|
tempfile.close();
|
|
|
|
|
remove(name);
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-07-23 11:45:10 +02:00
|
|
|
|
2017-12-21 00:45:38 +01:00
|
|
|
void setFileDescriptor(int fd) {
|
2020-04-08 18:14:19 +02:00
|
|
|
hwDeviceId = std::make_unique<HwDeviceId>(fd, "");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setPciPath(const char *pciPath) {
|
|
|
|
|
hwDeviceId = std::make_unique<HwDeviceId>(getFileDescriptor(), pciPath);
|
2017-12-21 00:45:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void setDeviceID(int deviceId) { this->deviceId = deviceId; }
|
|
|
|
|
void setDeviceRevID(int revisionId) { this->revisionId = revisionId; }
|
2020-11-19 20:43:01 +00:00
|
|
|
void setBindAvailable() {
|
|
|
|
|
this->bindAvailable = true;
|
|
|
|
|
}
|
2021-01-25 20:43:48 +00:00
|
|
|
void setContextDebugFlag(uint32_t drmContextId) override {
|
|
|
|
|
passedContextDebugId = drmContextId;
|
|
|
|
|
return Drm::setContextDebugFlag(drmContextId);
|
|
|
|
|
}
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2019-04-10 14:32:41 +02:00
|
|
|
static const int mockFd = 33;
|
|
|
|
|
|
2020-06-09 15:51:26 +02:00
|
|
|
bool failRetTopology = false;
|
2020-09-10 12:36:44 +02:00
|
|
|
bool baseErrno = true;
|
|
|
|
|
int errnoRetVal = 0;
|
2020-06-09 15:51:26 +02:00
|
|
|
int StoredEUVal = 8;
|
|
|
|
|
int StoredSSVal = 2;
|
|
|
|
|
int StoredSVal = 1;
|
2017-12-21 00:45:38 +01:00
|
|
|
int StoredDeviceID = 1;
|
|
|
|
|
int StoredDeviceRevID = 1;
|
|
|
|
|
int StoredHasPooledEU = 1;
|
|
|
|
|
int StoredMinEUinPool = 1;
|
2020-02-10 08:05:32 -08:00
|
|
|
int StoredPersistentContextsSupport = 1;
|
2017-12-21 00:45:38 +01:00
|
|
|
int StoredRetVal = 0;
|
2019-12-17 15:17:52 +01:00
|
|
|
int StoredRetValForGetGttSize = 0;
|
2019-08-21 03:50:47 -07:00
|
|
|
int StoredRetValForGetSSEU = 0;
|
|
|
|
|
int StoredRetValForSetSSEU = 0;
|
2017-12-21 00:45:38 +01:00
|
|
|
int StoredRetValForDeviceID = 0;
|
|
|
|
|
int StoredRetValForEUVal = 0;
|
|
|
|
|
int StoredRetValForSSVal = 0;
|
|
|
|
|
int StoredRetValForDeviceRevID = 0;
|
|
|
|
|
int StoredRetValForPooledEU = 0;
|
|
|
|
|
int StoredRetValForMinEUinPool = 0;
|
2020-02-10 08:05:32 -08:00
|
|
|
int StoredRetValForPersistant = 0;
|
2019-03-21 22:21:52 -07:00
|
|
|
int StoredPreemptionSupport =
|
|
|
|
|
I915_SCHEDULER_CAP_ENABLED |
|
|
|
|
|
I915_SCHEDULER_CAP_PRIORITY |
|
|
|
|
|
I915_SCHEDULER_CAP_PREEMPTION;
|
2017-12-21 00:45:38 +01:00
|
|
|
int StoredExecSoftPin = 0;
|
2020-08-17 12:07:39 +02:00
|
|
|
int StoredRetValForVmId = 1;
|
2020-06-09 15:51:26 +02:00
|
|
|
|
|
|
|
|
bool disableSomeTopology = false;
|
2021-01-25 20:43:48 +00:00
|
|
|
uint32_t passedContextDebugId = uint32_t(-1);
|
2020-06-09 15:51:26 +02:00
|
|
|
|
2020-07-07 09:34:31 +02:00
|
|
|
uint32_t receivedCreateContextId = 0;
|
2018-12-11 08:21:56 +01:00
|
|
|
uint32_t receivedDestroyContextId = 0;
|
2019-03-19 13:53:55 +01:00
|
|
|
uint32_t ioctlCallsCount = 0;
|
2018-12-11 08:21:56 +01:00
|
|
|
|
|
|
|
|
uint32_t receivedContextParamRequestCount = 0;
|
|
|
|
|
drm_i915_gem_context_param receivedContextParamRequest = {};
|
2017-12-21 00:45:38 +01:00
|
|
|
|
|
|
|
|
//DRM_IOCTL_I915_GEM_EXECBUFFER2
|
|
|
|
|
drm_i915_gem_execbuffer2 execBuffer = {0};
|
2020-09-21 13:52:17 +02:00
|
|
|
uint64_t bbFlags;
|
2017-12-21 00:45:38 +01:00
|
|
|
|
|
|
|
|
//DRM_IOCTL_I915_GEM_CREATE
|
|
|
|
|
__u64 createParamsSize = 0;
|
|
|
|
|
__u32 createParamsHandle = 0;
|
|
|
|
|
//DRM_IOCTL_I915_GEM_SET_TILING
|
|
|
|
|
__u32 setTilingMode = 0;
|
|
|
|
|
__u32 setTilingHandle = 0;
|
|
|
|
|
__u32 setTilingStride = 0;
|
|
|
|
|
//DRM_IOCTL_PRIME_FD_TO_HANDLE
|
|
|
|
|
__u32 outputHandle = 0;
|
|
|
|
|
__s32 inputFd = 0;
|
2020-10-21 10:50:53 +02:00
|
|
|
int fdToHandleRetVal = 0;
|
|
|
|
|
//DRM_IOCTL_HANDLE_TO_FD
|
|
|
|
|
__s32 outputFd = 0;
|
2017-12-21 00:45:38 +01:00
|
|
|
//DRM_IOCTL_I915_GEM_USERPTR
|
|
|
|
|
__u32 returnHandle = 0;
|
|
|
|
|
__u64 gpuMemSize = 3u * MemoryConstants::gigaByte;
|
2019-03-12 23:24:30 +01:00
|
|
|
//DRM_IOCTL_I915_GEM_MMAP
|
|
|
|
|
uint64_t lockedPtr[4];
|
2020-11-19 12:04:17 +01:00
|
|
|
//DRM_IOCTL_I915_QUERY
|
|
|
|
|
drm_i915_query_item storedQueryItem = {};
|
2017-12-21 00:45:38 +01:00
|
|
|
|
2019-04-23 15:42:33 +02:00
|
|
|
uint64_t storedGTTSize = 1ull << 47;
|
2019-08-21 03:50:47 -07:00
|
|
|
uint64_t storedParamSseu = ULONG_MAX;
|
2019-04-23 15:42:33 +02:00
|
|
|
|
2019-07-23 11:45:10 +02:00
|
|
|
virtual int handleRemainingRequests(unsigned long request, void *arg) { return -1; }
|
2017-12-21 00:45:38 +01:00
|
|
|
};
|
2020-08-11 14:00:41 +02:00
|
|
|
|
|
|
|
|
class DrmMockNonFailing : public DrmMock {
|
|
|
|
|
public:
|
|
|
|
|
using DrmMock::DrmMock;
|
|
|
|
|
int handleRemainingRequests(unsigned long request, void *arg) override { return 0; }
|
|
|
|
|
};
|
2020-08-24 13:08:59 -04:00
|
|
|
|
|
|
|
|
class DrmMockEngine : public DrmMock {
|
|
|
|
|
public:
|
|
|
|
|
uint32_t i915QuerySuccessCount = std::numeric_limits<uint32_t>::max();
|
|
|
|
|
uint32_t queryEngineInfoSuccessCount = std::numeric_limits<uint32_t>::max();
|
|
|
|
|
|
2020-09-11 14:18:23 +02:00
|
|
|
DrmMockEngine(RootDeviceEnvironment &rootDeviceEnvironment) : DrmMock(rootDeviceEnvironment) {}
|
|
|
|
|
|
2020-08-24 13:08:59 -04:00
|
|
|
virtual int handleRemainingRequests(unsigned long request, void *arg) {
|
|
|
|
|
if ((request == DRM_IOCTL_I915_QUERY) && (arg != nullptr)) {
|
|
|
|
|
if (i915QuerySuccessCount == 0) {
|
|
|
|
|
return EINVAL;
|
|
|
|
|
}
|
|
|
|
|
i915QuerySuccessCount--;
|
|
|
|
|
auto query = static_cast<drm_i915_query *>(arg);
|
|
|
|
|
if (query->items_ptr == 0) {
|
|
|
|
|
return EINVAL;
|
|
|
|
|
}
|
|
|
|
|
for (auto i = 0u; i < query->num_items; i++) {
|
|
|
|
|
handleQueryItem(reinterpret_cast<drm_i915_query_item *>(query->items_ptr) + i);
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void handleQueryItem(drm_i915_query_item *queryItem) {
|
|
|
|
|
switch (queryItem->query_id) {
|
|
|
|
|
case DRM_I915_QUERY_ENGINE_INFO:
|
|
|
|
|
if (queryEngineInfoSuccessCount == 0) {
|
|
|
|
|
queryItem->length = -EINVAL;
|
|
|
|
|
} else {
|
|
|
|
|
queryEngineInfoSuccessCount--;
|
|
|
|
|
auto numberOfEngines = 2u;
|
|
|
|
|
int engineInfoSize = sizeof(drm_i915_query_engine_info) + numberOfEngines * sizeof(drm_i915_engine_info);
|
|
|
|
|
if (queryItem->length == 0) {
|
|
|
|
|
queryItem->length = engineInfoSize;
|
|
|
|
|
} else {
|
|
|
|
|
EXPECT_EQ(engineInfoSize, queryItem->length);
|
|
|
|
|
auto queryEnginenInfo = reinterpret_cast<drm_i915_query_engine_info *>(queryItem->data_ptr);
|
|
|
|
|
EXPECT_EQ(0u, queryEnginenInfo->num_engines);
|
|
|
|
|
queryEnginenInfo->num_engines = numberOfEngines;
|
|
|
|
|
queryEnginenInfo->engines[0].engine.engine_class = I915_ENGINE_CLASS_RENDER;
|
|
|
|
|
queryEnginenInfo->engines[0].engine.engine_instance = 1;
|
|
|
|
|
queryEnginenInfo->engines[1].engine.engine_class = I915_ENGINE_CLASS_COPY;
|
|
|
|
|
queryEnginenInfo->engines[1].engine.engine_instance = 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
2020-09-14 13:28:47 +02:00
|
|
|
|
|
|
|
|
class DrmMockResources : public DrmMock {
|
|
|
|
|
public:
|
2020-11-23 14:31:20 +00:00
|
|
|
DrmMockResources(RootDeviceEnvironment &rootDeviceEnvironment) : DrmMock(mockFd, rootDeviceEnvironment) {
|
|
|
|
|
setBindAvailable();
|
|
|
|
|
}
|
2020-09-14 13:28:47 +02:00
|
|
|
|
|
|
|
|
bool registerResourceClasses() override {
|
|
|
|
|
registerClassesCalled = true;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-16 15:52:18 -07:00
|
|
|
uint32_t registerResource(ResourceClass classType, const void *data, size_t size) override {
|
2020-09-14 13:28:47 +02:00
|
|
|
registeredClass = classType;
|
2020-09-17 13:27:32 +02:00
|
|
|
memcpy_s(registeredData, sizeof(registeredData), data, size);
|
|
|
|
|
registeredDataSize = size;
|
2020-09-14 13:28:47 +02:00
|
|
|
return registerResourceReturnHandle;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void unregisterResource(uint32_t handle) override {
|
|
|
|
|
unregisterCalledCount++;
|
|
|
|
|
unregisteredHandle = handle;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-26 14:48:20 +01:00
|
|
|
uint32_t registerIsaCookie(uint32_t isaHanlde) override {
|
|
|
|
|
return currentCookie++;
|
|
|
|
|
}
|
|
|
|
|
|
2020-11-23 14:31:20 +00:00
|
|
|
bool isVmBindAvailable() override {
|
|
|
|
|
return bindAvailable;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-14 13:28:47 +02:00
|
|
|
static const uint32_t registerResourceReturnHandle;
|
|
|
|
|
|
|
|
|
|
uint32_t unregisteredHandle = 0;
|
|
|
|
|
uint32_t unregisterCalledCount = 0;
|
|
|
|
|
ResourceClass registeredClass = ResourceClass::MaxSize;
|
|
|
|
|
bool registerClassesCalled = false;
|
2020-09-17 13:27:32 +02:00
|
|
|
uint64_t registeredData[128];
|
|
|
|
|
size_t registeredDataSize;
|
2020-10-26 14:48:20 +01:00
|
|
|
uint32_t currentCookie = 2;
|
2020-09-14 13:28:47 +02:00
|
|
|
};
|