diff --git a/opencl/test/unit_test/os_interface/linux/ioctl_helper_tests_prelim.cpp b/opencl/test/unit_test/os_interface/linux/ioctl_helper_tests_prelim.cpp index 667c0c3e75..30f644590f 100644 --- a/opencl/test/unit_test/os_interface/linux/ioctl_helper_tests_prelim.cpp +++ b/opencl/test/unit_test/os_interface/linux/ioctl_helper_tests_prelim.cpp @@ -10,6 +10,7 @@ #include "shared/test/common/helpers/debug_manager_state_restore.h" #include "shared/test/common/helpers/default_hw_info.h" #include "shared/test/common/libult/linux/drm_mock.h" +#include "shared/test/common/mocks/linux/mock_drm_allocation.h" #include "shared/test/common/test_macros/test.h" using namespace NEO; @@ -194,3 +195,65 @@ TEST(IoctlHelperTestsPrelim, givenPrelimsWhenGetHwConfigIoctlValThenCorrectValue uint32_t ioctlVal = (1 << 16) | 6; EXPECT_EQ(ioctlVal, IoctlHelper::get(drm.get())->getHwConfigIoctlVal()); } + +TEST(IoctlHelperTestsPrelim, givenDrmAllocationWhenSetMemAdviseFailsThenDontUpdateMemAdviceFlags) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + + DrmPrelimMock drm(*executionEnvironment->rootDeviceEnvironments[0]); + drm.ioctlRetVal = -1; + + MockBufferObject bo(&drm, 0, 0, 1); + MockDrmAllocation allocation(GraphicsAllocation::AllocationType::BUFFER, MemoryPool::LocalMemory); + allocation.bufferObjects[0] = &bo; + + MemAdviseFlags memAdviseFlags{}; + memAdviseFlags.non_atomic = 1; + + allocation.setMemAdvise(&drm, memAdviseFlags); + + EXPECT_EQ(1u, drm.ioctlCallsCount); + EXPECT_NE(memAdviseFlags.memadvise_flags, allocation.enabledMemAdviseFlags.memadvise_flags); +} + +TEST(IoctlHelperTestsPrelim, givenDrmAllocationWhenSetMemAdviseWithNonAtomicIsCalledThenUpdateTheCorrespondingVmAdviceForBufferObject) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + + DrmPrelimMock drm(*executionEnvironment->rootDeviceEnvironments[0]); + + MockBufferObject bo(&drm, 0, 0, 1); + MockDrmAllocation allocation(GraphicsAllocation::AllocationType::BUFFER, MemoryPool::LocalMemory); + allocation.bufferObjects[0] = &bo; + + MemAdviseFlags memAdviseFlags{}; + + for (auto nonAtomic : {true, false}) { + memAdviseFlags.non_atomic = nonAtomic; + + EXPECT_TRUE(allocation.setMemAdvise(&drm, memAdviseFlags)); + EXPECT_EQ(memAdviseFlags.memadvise_flags, allocation.enabledMemAdviseFlags.memadvise_flags); + } + EXPECT_EQ(2u, drm.ioctlCallsCount); +} + +TEST(IoctlHelperTestsPrelim, givenDrmAllocationWhenSetMemAdviseWithDevicePreferredLocationIsCalledThenUpdateTheCorrespondingVmAdviceForBufferObject) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + + DrmPrelimMock drm(*executionEnvironment->rootDeviceEnvironments[0]); + + MockBufferObject bo(&drm, 0, 0, 1); + MockDrmAllocation allocation(GraphicsAllocation::AllocationType::BUFFER, MemoryPool::LocalMemory); + allocation.bufferObjects[0] = &bo; + + MemAdviseFlags memAdviseFlags{}; + + for (auto devicePreferredLocation : {true, false}) { + memAdviseFlags.device_preferred_location = devicePreferredLocation; + + EXPECT_TRUE(allocation.setMemAdvise(&drm, memAdviseFlags)); + EXPECT_EQ(memAdviseFlags.memadvise_flags, allocation.enabledMemAdviseFlags.memadvise_flags); + } + EXPECT_EQ(2u, drm.ioctlCallsCount); +} diff --git a/opencl/test/unit_test/os_interface/linux/ioctl_helper_tests_upstream.cpp b/opencl/test/unit_test/os_interface/linux/ioctl_helper_tests_upstream.cpp index 5e5e839c5a..532eb20211 100644 --- a/opencl/test/unit_test/os_interface/linux/ioctl_helper_tests_upstream.cpp +++ b/opencl/test/unit_test/os_interface/linux/ioctl_helper_tests_upstream.cpp @@ -91,3 +91,23 @@ TEST(IoctlHelperTestsUpstream, givenUpstreamWhenClosAllocWaysThenReturnZeroWays) EXPECT_EQ(0, cacheRegion); } + +TEST(IoctlHelperTestsUpstream, givenUpstreamWhenGetAdviseThenReturnCorrectValue) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + auto drm = std::make_unique(*executionEnvironment->rootDeviceEnvironments[0]); + + auto ioctlHelper = IoctlHelper::get(drm.get()); + EXPECT_EQ(0u, ioctlHelper->getAtomicAdvise(false)); + EXPECT_EQ(0u, ioctlHelper->getAtomicAdvise(true)); + EXPECT_EQ(0u, ioctlHelper->getPreferredLocationAdvise()); +} + +TEST(IoctlHelperTestsUpstream, givenUpstreamWhenSetVmBoAdviseThenReturnTrue) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + auto drm = std::make_unique(*executionEnvironment->rootDeviceEnvironments[0]); + + auto ioctlHelper = IoctlHelper::get(drm.get()); + EXPECT_TRUE(ioctlHelper->setVmBoAdvise(drm.get(), 0, 0, nullptr)); +} diff --git a/shared/source/os_interface/linux/drm_allocation.cpp b/shared/source/os_interface/linux/drm_allocation.cpp index 9b165a8829..294ebb83f6 100644 --- a/shared/source/os_interface/linux/drm_allocation.cpp +++ b/shared/source/os_interface/linux/drm_allocation.cpp @@ -10,6 +10,7 @@ #include "shared/source/memory_manager/residency.h" #include "shared/source/os_interface/linux/drm_buffer_object.h" #include "shared/source/os_interface/linux/drm_memory_manager.h" +#include "shared/source/os_interface/linux/ioctl_helper.h" #include "shared/source/os_interface/os_context.h" #include @@ -167,4 +168,46 @@ void DrmAllocation::markForCapture() { } } } + +bool DrmAllocation::setMemAdvise(Drm *drm, MemAdviseFlags flags) { + bool success = true; + + if (flags.cached_memory != enabledMemAdviseFlags.cached_memory) { + CachePolicy memType = flags.cached_memory ? CachePolicy::WriteBack : CachePolicy::Uncached; + setCachePolicy(memType); + } + + auto ioctlHelper = IoctlHelper::get(drm); + if (flags.non_atomic != enabledMemAdviseFlags.non_atomic) { + for (auto bo : bufferObjects) { + if (bo != nullptr) { + success &= ioctlHelper->setVmBoAdvise(drm, bo->peekHandle(), ioctlHelper->getAtomicAdvise(flags.non_atomic), nullptr); + } + } + } + + if (flags.device_preferred_location != enabledMemAdviseFlags.device_preferred_location) { + drm_i915_gem_memory_class_instance region{}; + for (auto handleId = 0u; handleId < EngineLimits::maxHandleCount; handleId++) { + auto bo = bufferObjects[handleId]; + if (bo != nullptr) { + if (flags.device_preferred_location) { + region.memory_class = I915_MEMORY_CLASS_DEVICE; + region.memory_instance = handleId; + } else { + region.memory_class = -1; + region.memory_instance = 0; + } + success &= ioctlHelper->setVmBoAdvise(drm, bo->peekHandle(), ioctlHelper->getPreferredLocationAdvise(), ®ion); + } + } + } + + if (success) { + enabledMemAdviseFlags = flags; + } + + return success; +} + } // namespace NEO diff --git a/shared/source/os_interface/linux/drm_allocation_extended.cpp b/shared/source/os_interface/linux/drm_allocation_extended.cpp index 49bf286a56..3f6da5fe16 100644 --- a/shared/source/os_interface/linux/drm_allocation_extended.cpp +++ b/shared/source/os_interface/linux/drm_allocation_extended.cpp @@ -31,17 +31,6 @@ bool DrmAllocation::setCacheRegion(Drm *drm, CacheRegion regionIndex) { return setCacheAdvice(drm, 0, regionIndex); } -bool DrmAllocation::setMemAdvise(Drm *drm, MemAdviseFlags flags) { - if (flags.cached_memory != enabledMemAdviseFlags.cached_memory) { - CachePolicy memType = flags.cached_memory ? CachePolicy::WriteBack : CachePolicy::Uncached; - setCachePolicy(memType); - } - - enabledMemAdviseFlags = flags; - - return true; -} - bool DrmAllocation::shouldAllocationPageFault(const Drm *drm) { return false; } diff --git a/shared/source/os_interface/linux/ioctl_helper.h b/shared/source/os_interface/linux/ioctl_helper.h index bebfd628c4..bf8204892f 100644 --- a/shared/source/os_interface/linux/ioctl_helper.h +++ b/shared/source/os_interface/linux/ioctl_helper.h @@ -33,6 +33,9 @@ class IoctlHelper { virtual int waitUserFence(Drm *drm, uint32_t ctxId, uint64_t address, uint64_t value, uint32_t dataWidth, int64_t timeout, uint16_t flags) = 0; virtual uint32_t getHwConfigIoctlVal() = 0; + virtual uint32_t getAtomicAdvise(bool isNonAtomic) = 0; + virtual uint32_t getPreferredLocationAdvise() = 0; + virtual bool setVmBoAdvise(Drm *drm, int32_t handle, uint32_t attribute, void *region) = 0; }; class IoctlHelperUpstream : public IoctlHelper { @@ -45,6 +48,9 @@ class IoctlHelperUpstream : public IoctlHelper { int waitUserFence(Drm *drm, uint32_t ctxId, uint64_t address, uint64_t value, uint32_t dataWidth, int64_t timeout, uint16_t flags) override; uint32_t getHwConfigIoctlVal() override; + uint32_t getAtomicAdvise(bool isNonAtomic) override; + uint32_t getPreferredLocationAdvise() override; + bool setVmBoAdvise(Drm *drm, int32_t handle, uint32_t attribute, void *region) override; }; template @@ -68,6 +74,9 @@ class IoctlHelperPrelim20 : public IoctlHelper { int waitUserFence(Drm *drm, uint32_t ctxId, uint64_t address, uint64_t value, uint32_t dataWidth, int64_t timeout, uint16_t flags) override; uint32_t getHwConfigIoctlVal() override; + uint32_t getAtomicAdvise(bool isNonAtomic) override; + uint32_t getPreferredLocationAdvise() override; + bool setVmBoAdvise(Drm *drm, int32_t handle, uint32_t attribute, void *region) override; }; } // namespace NEO diff --git a/shared/source/os_interface/linux/ioctl_helper_prelim.cpp b/shared/source/os_interface/linux/ioctl_helper_prelim.cpp index 57eca24010..aa8cc2ffca 100644 --- a/shared/source/os_interface/linux/ioctl_helper_prelim.cpp +++ b/shared/source/os_interface/linux/ioctl_helper_prelim.cpp @@ -136,4 +136,31 @@ 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(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; +} + } // namespace NEO diff --git a/shared/source/os_interface/linux/ioctl_helper_upstream.cpp b/shared/source/os_interface/linux/ioctl_helper_upstream.cpp index 88c54b0da5..dc1a64d761 100644 --- a/shared/source/os_interface/linux/ioctl_helper_upstream.cpp +++ b/shared/source/os_interface/linux/ioctl_helper_upstream.cpp @@ -67,4 +67,16 @@ uint32_t IoctlHelperUpstream::getHwConfigIoctlVal() { return DRM_I915_QUERY_HWCONFIG_TABLE; } +uint32_t IoctlHelperUpstream::getAtomicAdvise(bool isNonAtomic) { + return 0; +} + +uint32_t IoctlHelperUpstream::getPreferredLocationAdvise() { + return 0; +} + +bool IoctlHelperUpstream::setVmBoAdvise(Drm *drm, int32_t handle, uint32_t attribute, void *region) { + return true; +} + } // namespace NEO