Split buffer object validation and early pinning

Change-Id: If1b136807dc8593179ce743c8e0187ee80c3e95f
Signed-off-by: Lukasz Jobczyk <lukasz.jobczyk@intel.com>
This commit is contained in:
Lukasz Jobczyk
2020-10-16 13:46:25 +02:00
parent 6b0e12ed94
commit 3e762b25c0
5 changed files with 112 additions and 19 deletions

View File

@ -133,7 +133,7 @@ TEST_F(DrmBufferObjectTest, givenAddressThatWhenSizeIsAddedWithin32BitBoundaryWh
EXPECT_TRUE(execObject.flags & EXEC_OBJECT_SUPPORTS_48B_ADDRESS);
}
TEST_F(DrmBufferObjectTest, onPinIoctlFailed) {
TEST_F(DrmBufferObjectTest, whenExecFailsThenPinFails) {
std::unique_ptr<uint32_t[]> buff(new uint32_t[1024]);
mock->ioctl_expected.total = 1;
@ -145,7 +145,23 @@ TEST_F(DrmBufferObjectTest, onPinIoctlFailed) {
bo->setAddress(reinterpret_cast<uint64_t>(buff.get()));
BufferObject *boArray[1] = {boToPin.get()};
auto ret = bo->pin(boArray, 1, osContext.get(), 0, 1, true);
auto ret = bo->pin(boArray, 1, osContext.get(), 0, 1);
EXPECT_EQ(EINVAL, ret);
}
TEST_F(DrmBufferObjectTest, whenExecFailsThenValidateHostPtrFails) {
std::unique_ptr<uint32_t[]> buff(new uint32_t[1024]);
mock->ioctl_expected.total = 1;
mock->ioctl_res = -1;
this->mock->errnoValue = EINVAL;
std::unique_ptr<BufferObject> boToPin(new TestedBufferObject(this->mock.get()));
ASSERT_NE(nullptr, boToPin.get());
bo->setAddress(reinterpret_cast<uint64_t>(buff.get()));
BufferObject *boArray[1] = {boToPin.get()};
auto ret = bo->validateHostPtr(boArray, 1, osContext.get(), 0, 1);
EXPECT_EQ(EINVAL, ret);
}
@ -161,7 +177,7 @@ TEST_F(DrmBufferObjectTest, givenResidentBOWhenPrintExecutionBufferIsSetToTrueTh
BufferObject *boArray[1] = {bo.get()};
testing::internal::CaptureStdout();
auto ret = bo->pin(boArray, 1, osContext.get(), 0, 1, true);
auto ret = bo->pin(boArray, 1, osContext.get(), 0, 1);
EXPECT_EQ(0, ret);
std::string output = testing::internal::GetCapturedStdout();
@ -207,6 +223,29 @@ TEST_F(DrmBufferObjectTest, whenPrintExecutionBufferIsSetToTrueThenMessageFoundI
EXPECT_EQ(expectedValue, idx);
}
TEST(DrmBufferObjectSimpleTest, givenInvalidBoWhenValidateHostptrIsCalledThenErrorIsReturned) {
std::unique_ptr<uint32_t[]> buff(new uint32_t[256]);
std::unique_ptr<DrmMockCustom> mock(new DrmMockCustom);
OsContextLinux osContext(*mock, 0u, 1, aub_stream::ENGINE_RCS, PreemptionMode::Disabled, false, false, false);
ASSERT_NE(nullptr, mock.get());
std::unique_ptr<TestedBufferObject> bo(new TestedBufferObject(mock.get()));
ASSERT_NE(nullptr, bo.get());
// fail DRM_IOCTL_I915_GEM_EXECBUFFER2 in pin
mock->ioctl_res = -1;
std::unique_ptr<BufferObject> boToPin(new TestedBufferObject(mock.get()));
ASSERT_NE(nullptr, boToPin.get());
bo->setAddress(reinterpret_cast<uint64_t>(buff.get()));
mock->errnoValue = EFAULT;
BufferObject *boArray[1] = {boToPin.get()};
auto ret = bo->pin(boArray, 1, &osContext, 0, 1);
EXPECT_EQ(EFAULT, ret);
mock->ioctl_res = 0;
}
TEST(DrmBufferObjectSimpleTest, givenInvalidBoWhenPinIsCalledThenErrorIsReturned) {
std::unique_ptr<uint32_t[]> buff(new uint32_t[256]);
std::unique_ptr<DrmMockCustom> mock(new DrmMockCustom);
@ -225,7 +264,7 @@ TEST(DrmBufferObjectSimpleTest, givenInvalidBoWhenPinIsCalledThenErrorIsReturned
mock->errnoValue = EFAULT;
BufferObject *boArray[1] = {boToPin.get()};
auto ret = bo->pin(boArray, 1, &osContext, 0, 1, true);
auto ret = bo->validateHostPtr(boArray, 1, &osContext, 0, 1);
EXPECT_EQ(EFAULT, ret);
mock->ioctl_res = 0;
}
@ -258,7 +297,40 @@ TEST(DrmBufferObjectSimpleTest, givenArrayOfBosWhenPinnedThenAllBosArePinned) {
BufferObject *array[3] = {boToPin.get(), boToPin2.get(), boToPin3.get()};
bo->setAddress(reinterpret_cast<uint64_t>(buff.get()));
auto ret = bo->pin(array, 3, &osContext, 0, 1, true);
auto ret = bo->pin(array, 3, &osContext, 0, 1);
EXPECT_EQ(mock->ioctl_res, ret);
EXPECT_LT(0u, mock->execBuffer.batch_len);
EXPECT_EQ(4u, mock->execBuffer.buffer_count); // 3 bos to pin plus 1 exec bo
EXPECT_EQ(reinterpret_cast<uintptr_t>(boToPin->execObjectPointerFilled), mock->execBuffer.buffers_ptr);
EXPECT_NE(nullptr, boToPin2->execObjectPointerFilled);
EXPECT_NE(nullptr, boToPin3->execObjectPointerFilled);
bo->setAddress(0llu);
}
TEST(DrmBufferObjectSimpleTest, givenArrayOfBosWhenValidatedThenAllBosArePinned) {
std::unique_ptr<uint32_t[]> buff(new uint32_t[256]);
std::unique_ptr<DrmMockCustom> mock(new DrmMockCustom);
ASSERT_NE(nullptr, mock.get());
OsContextLinux osContext(*mock, 0u, 1, aub_stream::ENGINE_RCS, PreemptionMode::Disabled, false, false, false);
std::unique_ptr<TestedBufferObject> bo(new TestedBufferObject(mock.get()));
ASSERT_NE(nullptr, bo.get());
mock->ioctl_res = 0;
std::unique_ptr<TestedBufferObject> boToPin(new TestedBufferObject(mock.get()));
std::unique_ptr<TestedBufferObject> boToPin2(new TestedBufferObject(mock.get()));
std::unique_ptr<TestedBufferObject> boToPin3(new TestedBufferObject(mock.get()));
ASSERT_NE(nullptr, boToPin.get());
ASSERT_NE(nullptr, boToPin2.get());
ASSERT_NE(nullptr, boToPin3.get());
BufferObject *array[3] = {boToPin.get(), boToPin2.get(), boToPin3.get()};
bo->setAddress(reinterpret_cast<uint64_t>(buff.get()));
auto ret = bo->validateHostPtr(array, 3, &osContext, 0, 1);
EXPECT_EQ(mock->ioctl_res, ret);
EXPECT_LT(0u, mock->execBuffer.batch_len);

View File

@ -3118,7 +3118,7 @@ TEST_F(DrmMemoryManagerWithExplicitExpectationsTest, givenDisabledForcePinAndEna
PinBufferObject(Drm *drm) : BufferObject(drm, 1, 0, 1) {
}
int pin(BufferObject *const boToPin[], size_t numberOfBos, OsContext *osContext, uint32_t vmHandleId, uint32_t drmContextId, bool validateHostptr) override {
int validateHostPtr(BufferObject *const boToPin[], size_t numberOfBos, OsContext *osContext, uint32_t vmHandleId, uint32_t drmContextId) override {
for (size_t i = 0; i < numberOfBos; i++) {
pinnedBoArray[i] = boToPin[i];
}

View File

@ -205,18 +205,38 @@ void BufferObject::printExecutionBuffer(drm_i915_gem_execbuffer2 &execbuf, const
std::cout << logger.str() << std::endl;
}
int BufferObject::pin(BufferObject *const boToPin[], size_t numberOfBos, OsContext *osContext, uint32_t vmHandleId, uint32_t drmContextId, bool validateHostPtr) {
int bindBOsWithinContext(BufferObject *const boToPin[], size_t numberOfBos, OsContext *osContext, uint32_t vmHandleId) {
auto retVal = 0;
if ((validateHostPtr && osContext->isDirectSubmissionActive()) ||
(!validateHostPtr && this->drm->isBindAvailable())) {
for (auto drmIterator = 0u; drmIterator < osContext->getDeviceBitfield().size(); drmIterator++) {
if (osContext->getDeviceBitfield().test(drmIterator)) {
for (size_t i = 0; i < numberOfBos; i++) {
retVal |= boToPin[i]->bind(osContext, drmIterator);
}
for (auto drmIterator = 0u; drmIterator < osContext->getDeviceBitfield().size(); drmIterator++) {
if (osContext->getDeviceBitfield().test(drmIterator)) {
for (size_t i = 0; i < numberOfBos; i++) {
retVal |= boToPin[i]->bind(osContext, drmIterator);
}
}
}
return retVal;
}
int BufferObject::pin(BufferObject *const boToPin[], size_t numberOfBos, OsContext *osContext, uint32_t vmHandleId, uint32_t drmContextId) {
auto retVal = 0;
if (this->drm->isBindAvailable()) {
retVal = bindBOsWithinContext(boToPin, numberOfBos, osContext, vmHandleId);
} else {
StackVec<drm_i915_gem_exec_object2, maxFragmentsCount + 1> execObject(numberOfBos + 1);
retVal = this->exec(4u, 0u, 0u, false, osContext, vmHandleId, drmContextId, boToPin, numberOfBos, &execObject[0]);
}
return retVal;
}
int BufferObject::validateHostPtr(BufferObject *const boToPin[], size_t numberOfBos, OsContext *osContext, uint32_t vmHandleId, uint32_t drmContextId) {
auto retVal = 0;
if (osContext->isDirectSubmissionActive()) {
retVal = bindBOsWithinContext(boToPin, numberOfBos, osContext, vmHandleId);
} else {
StackVec<drm_i915_gem_exec_object2, maxFragmentsCount + 1> execObject(numberOfBos + 1);
retVal = this->exec(4u, 0u, 0u, false, osContext, vmHandleId, drmContextId, boToPin, numberOfBos, &execObject[0]);

View File

@ -43,7 +43,8 @@ class BufferObject {
bool setTiling(uint32_t mode, uint32_t stride);
MOCKABLE_VIRTUAL int pin(BufferObject *const boToPin[], size_t numberOfBos, OsContext *osContext, uint32_t vmHandleId, uint32_t drmContextId, bool validateHostptr);
int pin(BufferObject *const boToPin[], size_t numberOfBos, OsContext *osContext, uint32_t vmHandleId, uint32_t drmContextId);
MOCKABLE_VIRTUAL int validateHostPtr(BufferObject *const boToPin[], size_t numberOfBos, OsContext *osContext, uint32_t vmHandleId, uint32_t drmContextId);
int exec(uint32_t used, size_t startOffset, unsigned int flags, bool requiresCoherency, OsContext *osContext, uint32_t vmHandleId, uint32_t drmContextId, BufferObject *const residency[], size_t residencyCount, drm_i915_gem_exec_object2 *execObjectsStorage);

View File

@ -199,7 +199,7 @@ NEO::BufferObject *DrmMemoryManager::allocUserptr(uintptr_t address, size_t size
void DrmMemoryManager::emitPinningRequest(BufferObject *bo, const AllocationData &allocationData) const {
if (forcePinEnabled && pinBBs.at(allocationData.rootDeviceIndex) != nullptr && allocationData.flags.forcePin && allocationData.size >= this->pinThreshold) {
pinBBs.at(allocationData.rootDeviceIndex)->pin(&bo, 1, registeredEngines[defaultEngineIndex].osContext, 0, getDefaultDrmContextId(), false);
pinBBs.at(allocationData.rootDeviceIndex)->pin(&bo, 1, registeredEngines[defaultEngineIndex].osContext, 0, getDefaultDrmContextId());
}
}
@ -344,7 +344,7 @@ GraphicsAllocation *DrmMemoryManager::allocateGraphicsMemoryWithGpuVa(const Allo
BufferObject *boPtr = bo.get();
if (forcePinEnabled && pinBBs.at(allocationData.rootDeviceIndex) != nullptr && alignedSize >= this->pinThreshold) {
pinBBs.at(allocationData.rootDeviceIndex)->pin(&boPtr, 1, osContextLinux, 0, osContextLinux->getDrmContextIds()[0], false);
pinBBs.at(allocationData.rootDeviceIndex)->pin(&boPtr, 1, osContextLinux, 0, osContextLinux->getDrmContextIds()[0]);
}
auto allocation = new DrmAllocation(allocationData.rootDeviceIndex, allocationData.type, bo.get(), res, bo->gpuAddress, alignedSize, MemoryPool::System4KBPages);
@ -378,7 +378,7 @@ DrmAllocation *DrmMemoryManager::allocateGraphicsMemoryForNonSvmHostPtr(const Al
if (validateHostPtrMemory) {
auto boPtr = bo.get();
int result = pinBBs.at(allocationData.rootDeviceIndex)->pin(&boPtr, 1, registeredEngines[defaultEngineIndex].osContext, 0, getDefaultDrmContextId(), true);
int result = pinBBs.at(allocationData.rootDeviceIndex)->validateHostPtr(&boPtr, 1, registeredEngines[defaultEngineIndex].osContext, 0, getDefaultDrmContextId());
if (result != SUCCESS) {
unreference(bo.release(), true);
releaseGpuRange(reinterpret_cast<void *>(gpuVirtualAddress), alignedSize, allocationData.rootDeviceIndex);
@ -745,7 +745,7 @@ MemoryManager::AllocationStatus DrmMemoryManager::populateOsHandles(OsHandleStor
}
if (validateHostPtrMemory) {
int result = pinBBs.at(rootDeviceIndex)->pin(allocatedBos, numberOfBosAllocated, registeredEngines[defaultEngineIndex].osContext, 0, getDefaultDrmContextId(), true);
int result = pinBBs.at(rootDeviceIndex)->validateHostPtr(allocatedBos, numberOfBosAllocated, registeredEngines[defaultEngineIndex].osContext, 0, getDefaultDrmContextId());
if (result == EFAULT) {
for (uint32_t i = 0; i < numberOfBosAllocated; i++) {