Propagate exec buffer error to L0 API level

This change makes that drm file is opened in nonblocking mode for prelim
kernels. In such case when calling exec buffer ioctl and get
EAGAIN (aka EWOULDBLOCK) we may return error to API level

Related-To: NEO-7144
Signed-off-by: Mateusz Jablonski <mateusz.jablonski@intel.com>
This commit is contained in:
Mateusz Jablonski
2022-08-25 15:49:58 +00:00
committed by Compute-Runtime-Automation
parent 5c48e027b9
commit 9a95f3c62d
24 changed files with 244 additions and 18 deletions

View File

@@ -193,7 +193,7 @@ int DrmMock::ioctl(DrmIoctl request, void *arg) {
for (uint32_t i = 0; i < execbuf->getBufferCount(); i++) {
this->receivedBos.push_back(execObjects[i]);
}
return 0;
return execBufferResult;
}
if (request == DrmIoctl::GemUserptr) {
ioctlCount.gemUserptr++;

View File

@@ -212,6 +212,7 @@ class DrmMock : public Drm {
//DRM_IOCTL_I915_GEM_EXECBUFFER2
std::vector<MockExecBuffer> execBuffers{};
std::vector<MockExecObject> receivedBos{};
int execBufferResult = 0;
//DRM_IOCTL_I915_GEM_CREATE
uint64_t createParamsSize = 0;
uint32_t createParamsHandle = 0;

View File

@@ -8,12 +8,15 @@
#pragma once
#include "shared/source/os_interface/linux/drm_buffer_object.h"
#include "shared/source/os_interface/linux/drm_memory_operations_handler_default.h"
#include "shared/source/os_interface/linux/drm_wrappers.h"
#include "shared/source/os_interface/linux/os_context_linux.h"
#include "shared/test/common/helpers/engine_descriptor_helper.h"
#include "shared/test/common/mocks/mock_execution_environment.h"
#include <memory>
using namespace NEO;
class TestedBufferObject : public BufferObject {
public:
using BufferObject::handle;

View File

@@ -20,6 +20,14 @@
#include <algorithm>
template <typename GfxFamily>
struct MockDrmCsr : public DrmCommandStreamReceiver<GfxFamily> {
using DrmCommandStreamReceiver<GfxFamily>::DrmCommandStreamReceiver;
using DrmCommandStreamReceiver<GfxFamily>::dispatchMode;
using DrmCommandStreamReceiver<GfxFamily>::completionFenceValuePointer;
using DrmCommandStreamReceiver<GfxFamily>::flushInternal;
};
class DrmCommandStreamTest : public ::testing::Test {
public:
template <typename GfxFamily>
@@ -43,7 +51,7 @@ class DrmCommandStreamTest : public ::testing::Test {
PreemptionHelper::getDefaultPreemptionMode(*hwInfo)));
osContext->ensureContextInitialized();
csr = new DrmCommandStreamReceiver<GfxFamily>(executionEnvironment, 0, 1, gemCloseWorkerMode::gemCloseWorkerActive);
csr = new MockDrmCsr<GfxFamily>(executionEnvironment, 0, 1, gemCloseWorkerMode::gemCloseWorkerActive);
ASSERT_NE(nullptr, csr);
csr->setupContext(*osContext);

View File

@@ -5,6 +5,8 @@
*
*/
#include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h"
#include "shared/source/helpers/string.h"
#include "shared/source/os_interface/linux/drm_wrappers.h"
#include "shared/source/os_interface/linux/i915.h"
@@ -17,6 +19,7 @@
#include <cstdio>
#include <cstring>
#include <dlfcn.h>
#include <fcntl.h>
#include <iostream>
#include <poll.h>
#include <stdio.h>
@@ -31,7 +34,6 @@ int closeFuncArgPassed = 0;
int closeFuncRetVal = 0;
int dlOpenFlags = 0;
bool dlOpenCalled = 0;
constexpr int fakeFileDescriptor = 123;
bool makeFakeDevicePath = false;
bool allowFakeDevicePath = false;
constexpr unsigned long int invalidIoctl = static_cast<unsigned long int>(-1);
@@ -43,6 +45,9 @@ uint32_t mmapFuncCalled = 0u;
uint32_t munmapFuncCalled = 0u;
bool isInvalidAILTest = false;
const char *drmVersion = "i915";
int passedFileDescriptorFlagsToSet = 0;
int getFileDescriptorFlagsCalled = 0;
int setFileDescriptorFlagsCalled = 0;
int (*sysCallsOpen)(const char *pathname, int flags) = nullptr;
ssize_t (*sysCallsPread)(int fd, void *buf, size_t count, off_t offset) = nullptr;
@@ -195,5 +200,21 @@ ssize_t read(int fd, void *buf, size_t count) {
return 0;
}
int fcntl(int fd, int cmd) {
if (cmd == F_GETFL) {
getFileDescriptorFlagsCalled++;
return O_RDWR;
}
return 0;
}
int fcntl(int fd, int cmd, int arg) {
if (cmd == F_SETFL) {
setFileDescriptorFlagsCalled++;
passedFileDescriptorFlagsToSet = arg;
}
return 0;
}
} // namespace SysCalls
} // namespace NEO

View File

@@ -21,5 +21,9 @@ extern int (*sysCallsPoll)(struct pollfd *pollFd, unsigned long int numberOfFds,
extern ssize_t (*sysCallsRead)(int fd, void *buf, size_t count);
extern const char *drmVersion;
constexpr int fakeFileDescriptor = 123;
extern int passedFileDescriptorFlagsToSet;
extern int getFileDescriptorFlagsCalled;
extern int setFileDescriptorFlagsCalled;
} // namespace SysCalls
} // namespace NEO

View File

@@ -6,7 +6,9 @@
*/
#include "shared/source/helpers/api_specific_config.h"
#include "shared/test/common/mocks/linux/mock_drm_allocation.h"
#include "shared/test/common/mocks/mock_graphics_allocation.h"
#include "shared/test/common/os_interface/linux/drm_buffer_object_fixture.h"
#include "shared/test/common/os_interface/linux/drm_command_stream_fixture.h"
#include "shared/test/common/test_macros/hw_test.h"
@@ -15,13 +17,6 @@ extern ApiSpecificConfig::ApiType apiTypeForUlts;
} //namespace NEO
using namespace NEO;
template <typename GfxFamily>
struct MockDrmCsr : public DrmCommandStreamReceiver<GfxFamily> {
using DrmCommandStreamReceiver<GfxFamily>::DrmCommandStreamReceiver;
using DrmCommandStreamReceiver<GfxFamily>::dispatchMode;
using DrmCommandStreamReceiver<GfxFamily>::completionFenceValuePointer;
};
HWTEST_TEMPLATED_F(DrmCommandStreamTest, givenL0ApiConfigWhenCreatingDrmCsrThenEnableImmediateDispatch) {
VariableBackup<ApiSpecificConfig::ApiType> backup(&apiTypeForUlts, ApiSpecificConfig::L0);
MockDrmCsr<FamilyType> csr(executionEnvironment, 0, 1, gemCloseWorkerMode::gemCloseWorkerInactive);
@@ -75,3 +70,20 @@ HWTEST_TEMPLATED_F(DrmCommandStreamTest, givenNoTagAddressWhenGettingCompletionA
EXPECT_EQ(nullptr, csr->getTagAddress());
EXPECT_EQ(0u, csr->getCompletionAddress());
}
HWTEST_TEMPLATED_F(DrmCommandStreamTest, GivenExecBufferErrorWhenFlushInternalThenProperErrorIsReturned) {
mock->execBufferResult = -1;
mock->baseErrno = false;
mock->errnoRetVal = EWOULDBLOCK;
TestedBufferObject bo(mock, 128);
MockDrmAllocation cmdBuffer(AllocationType::COMMAND_BUFFER, MemoryPool::System4KBPages);
cmdBuffer.bufferObjects[0] = &bo;
uint8_t buff[128]{};
LinearStream cs(&cmdBuffer, buff, 128);
BatchBuffer batchBuffer{cs.getGraphicsAllocation(), 0, 0, nullptr, false, false, QueueThrottle::MEDIUM, QueueSliceCount::defaultSliceCount, cs.getUsed(), &cs, nullptr, false};
auto ret = static_cast<MockDrmCsr<FamilyType> *>(csr)->flushInternal(batchBuffer, csr->getResidencyAllocations());
EXPECT_EQ(SubmissionStatus::OUT_OF_HOST_MEMORY, ret);
}

View File

@@ -884,12 +884,6 @@ HWTEST_TEMPLATED_F(DrmCommandStreamBlitterDirectSubmissionTest, givenEnabledDire
EXPECT_EQ(nullptr, static_cast<TestedDrmCommandStreamReceiver<FamilyType> *>(csr)->directSubmission.get());
}
template <typename GfxFamily>
struct MockDrmCsr : public DrmCommandStreamReceiver<GfxFamily> {
using DrmCommandStreamReceiver<GfxFamily>::DrmCommandStreamReceiver;
using DrmCommandStreamReceiver<GfxFamily>::dispatchMode;
};
HWTEST_TEMPLATED_F(DrmCommandStreamTest, givenDrmCommandStreamReceiverWhenCreatePageTableManagerIsCalledThenCreatePageTableManager) {
executionEnvironment.prepareRootDeviceEnvironments(2);
executionEnvironment.rootDeviceEnvironments[1]->setHwInfo(defaultHwInfo.get());

View File

@@ -10,7 +10,9 @@
#include "shared/source/os_interface/linux/i915_prelim.h"
#include "shared/source/os_interface/linux/ioctl_helper.h"
#include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "shared/test/common/helpers/variable_backup.h"
#include "shared/test/common/mocks/mock_execution_environment.h"
#include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h"
#include "shared/test/common/test_macros/test.h"
using namespace NEO;
@@ -348,3 +350,22 @@ TEST_F(IoctlPrelimHelperTests, givenPrelimWhenGettingEuStallPropertiesThenCorrec
TEST_F(IoctlPrelimHelperTests, givenPrelimWhenGettingEuStallFdParameterThenCorrectIoctlValueIsReturned) {
EXPECT_EQ(static_cast<uint32_t>(PRELIM_I915_PERF_FLAG_FD_EU_STALL), ioctlHelper.getEuStallFdParameter());
}
TEST_F(IoctlPrelimHelperTests, whenCallingIoctlWithGemExecbufferThenShouldBreakOnWouldBlock) {
EXPECT_TRUE(ioctlHelper.shouldBreakIoctlLoopOnWouldBlock(DrmIoctl::GemExecbuffer2));
EXPECT_FALSE(ioctlHelper.shouldBreakIoctlLoopOnWouldBlock(DrmIoctl::GemVmBind));
}
TEST(IoctlPrelimHelperTest, whenCreatingIoctlHelperThenProperFlagsAreSetToFileDescriptor) {
MockExecutionEnvironment executionEnvironment{};
std::unique_ptr<Drm> drm{Drm::create(std::make_unique<HwDeviceIdDrm>(0, ""), *executionEnvironment.rootDeviceEnvironments[0])};
VariableBackup<decltype(SysCalls::getFileDescriptorFlagsCalled)> backupGetFlags(&SysCalls::getFileDescriptorFlagsCalled, 0);
VariableBackup<decltype(SysCalls::setFileDescriptorFlagsCalled)> backupSetFlags(&SysCalls::setFileDescriptorFlagsCalled, 0);
VariableBackup<decltype(SysCalls::passedFileDescriptorFlagsToSet)> backupPassedFlags(&SysCalls::passedFileDescriptorFlagsToSet, 0);
IoctlHelperPrelim20 ioctlHelper{*drm};
EXPECT_EQ(1, SysCalls::getFileDescriptorFlagsCalled);
EXPECT_EQ(1, SysCalls::setFileDescriptorFlagsCalled);
EXPECT_EQ((O_RDWR | O_NONBLOCK), SysCalls::passedFileDescriptorFlagsToSet);
}

View File

@@ -477,3 +477,11 @@ TEST(IoctlHelperTestsUpstream, givenUpstreamWhenInitializingThenTrueIsReturned)
IoctlHelperUpstream ioctlHelper{*drm};
EXPECT_EQ(true, ioctlHelper.initialize());
}
TEST(IoctlHelperUpstreamTest, whenCallingIoctlWithGemExecbufferThenShouldNotBreakOnWouldBlock) {
auto executionEnvironment = std::make_unique<MockExecutionEnvironment>();
auto drm = std::make_unique<DrmTipMock>(*executionEnvironment->rootDeviceEnvironments[0]);
IoctlHelperUpstream ioctlHelper{*drm};
EXPECT_FALSE(ioctlHelper.shouldBreakIoctlLoopOnWouldBlock(DrmIoctl::GemExecbuffer2));
EXPECT_FALSE(ioctlHelper.shouldBreakIoctlLoopOnWouldBlock(DrmIoctl::GemVmBind));
}