1 /*
2  * Copyright (C) 2020-2021 Intel Corporation
3  *
4  * SPDX-License-Identifier: MIT
5  *
6  */
7 
8 #include "shared/source/execution_environment/execution_environment.h"
9 #include "shared/source/gmm_helper/gmm_helper.h"
10 #include "shared/source/helpers/heap_assigner.h"
11 #include "shared/source/os_interface/linux/allocator_helper.h"
12 #include "shared/source/os_interface/linux/drm_memory_manager.h"
13 #include "shared/source/os_interface/linux/drm_memory_operations_handler.h"
14 #include "shared/source/os_interface/os_interface.h"
15 #include "shared/test/common/helpers/debug_manager_state_restore.h"
16 #include "shared/test/common/mocks/linux/mock_drm_memory_manager.h"
17 #include "shared/test/common/mocks/mock_execution_environment.h"
18 #include "shared/test/common/mocks/mock_gmm.h"
19 #include "shared/test/common/test_macros/test.h"
20 
21 #include "opencl/test/unit_test/mocks/mock_context.h"
22 #include "opencl/test/unit_test/mocks/mock_platform.h"
23 #include "opencl/test/unit_test/os_interface/linux/drm_memory_manager_tests_impl.h"
24 #include "opencl/test/unit_test/os_interface/linux/drm_mock_impl.h"
25 #include "opencl/test/unit_test/os_interface/linux/drm_mock_memory_info.h"
26 
27 #include "gtest/gtest.h"
28 
29 namespace NEO {
30 
31 BufferObject *createBufferObjectInMemoryRegion(Drm *drm, uint64_t gpuAddress, size_t size, uint32_t memoryBanks, size_t maxOsContextCount);
32 
33 class DrmMemoryManagerLocalMemoryTest : public ::testing::Test {
34   public:
35     DrmTipMock *mock;
36 
SetUp()37     void SetUp() override {
38         const bool localMemoryEnabled = true;
39         executionEnvironment = new ExecutionEnvironment;
40         executionEnvironment->prepareRootDeviceEnvironments(1);
41         executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->setHwInfo(defaultHwInfo.get());
42         mock = new DrmTipMock(*executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]);
43         mock->memoryInfo.reset(new MockMemoryInfo());
44         executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->osInterface = std::make_unique<OSInterface>();
45         executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->osInterface->setDriverModel(std::unique_ptr<DriverModel>(mock));
46         executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*mock, 0u);
47 
48         device.reset(MockDevice::createWithExecutionEnvironment<MockDevice>(defaultHwInfo.get(), executionEnvironment, rootDeviceIndex));
49         memoryManager = std::make_unique<TestedDrmMemoryManager>(localMemoryEnabled, false, false, *executionEnvironment);
50     }
51 
isAllocationWithinHeap(const GraphicsAllocation & allocation,HeapIndex heap)52     bool isAllocationWithinHeap(const GraphicsAllocation &allocation, HeapIndex heap) {
53         const auto allocationStart = allocation.getGpuAddress();
54         const auto allocationEnd = allocationStart + allocation.getUnderlyingBufferSize();
55         const auto heapStart = GmmHelper::canonize(memoryManager->getGfxPartition(rootDeviceIndex)->getHeapBase(heap));
56         const auto heapEnd = GmmHelper::canonize(memoryManager->getGfxPartition(rootDeviceIndex)->getHeapLimit(heap));
57         return heapStart <= allocationStart && allocationEnd <= heapEnd;
58     }
59 
60   protected:
61     DebugManagerStateRestore restorer{};
62     ExecutionEnvironment *executionEnvironment = nullptr;
63     std::unique_ptr<MockDevice> device;
64     std::unique_ptr<TestedDrmMemoryManager> memoryManager;
65     const uint32_t rootDeviceIndex = 0u;
66 };
67 
68 class DrmMemoryManagerLocalMemoryWithCustomMockTest : public ::testing::Test {
69   public:
70     DrmMockCustomImpl *mock;
71 
SetUp()72     void SetUp() override {
73         const bool localMemoryEnabled = true;
74         executionEnvironment = new ExecutionEnvironment;
75         executionEnvironment->prepareRootDeviceEnvironments(1);
76         executionEnvironment->rootDeviceEnvironments[0]->setHwInfo(defaultHwInfo.get());
77         mock = new DrmMockCustomImpl(*executionEnvironment->rootDeviceEnvironments[0]);
78         executionEnvironment->rootDeviceEnvironments[0]->osInterface = std::make_unique<OSInterface>();
79         executionEnvironment->rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr<DriverModel>(mock));
80 
81         device.reset(MockDevice::createWithExecutionEnvironment<MockDevice>(defaultHwInfo.get(), executionEnvironment, 0));
82         memoryManager = std::make_unique<TestedDrmMemoryManager>(localMemoryEnabled, false, false, *executionEnvironment);
83     }
84 
85   protected:
86     ExecutionEnvironment *executionEnvironment = nullptr;
87     std::unique_ptr<MockDevice> device;
88     std::unique_ptr<TestedDrmMemoryManager> memoryManager;
89 };
90 
HWTEST2_F(DrmMemoryManagerLocalMemoryTest,givenDrmMemoryManagerWhenCreateBufferObjectInMemoryRegionIsCalledThenBufferObjectWithAGivenGpuAddressAndSizeIsCreatedAndAllocatedInASpecifiedMemoryRegion,NonDefaultIoctlsSupported)91 HWTEST2_F(DrmMemoryManagerLocalMemoryTest, givenDrmMemoryManagerWhenCreateBufferObjectInMemoryRegionIsCalledThenBufferObjectWithAGivenGpuAddressAndSizeIsCreatedAndAllocatedInASpecifiedMemoryRegion, NonDefaultIoctlsSupported) {
92     DebugManagerStateRestore restorer;
93     DebugManager.flags.EnableLocalMemory.set(1);
94     MemoryRegion regionInfo[2] = {};
95     regionInfo[0].region = {I915_MEMORY_CLASS_SYSTEM, 0};
96     regionInfo[1].region = {I915_MEMORY_CLASS_DEVICE, 0};
97 
98     mock->memoryInfo.reset(new MemoryInfo(regionInfo, 2));
99     mock->ioctlCallsCount = 0;
100 
101     auto gpuAddress = 0x1234u;
102     auto size = MemoryConstants::pageSize64k;
103 
104     auto bo = std::unique_ptr<BufferObject>(memoryManager->createBufferObjectInMemoryRegion(&memoryManager->getDrm(0),
105                                                                                             gpuAddress,
106                                                                                             size,
107                                                                                             (1 << (MemoryBanks::getBankForLocalMemory(0) - 1)),
108                                                                                             1));
109     ASSERT_NE(nullptr, bo);
110     EXPECT_EQ(1u, mock->ioctlCallsCount);
111     EXPECT_EQ(1u, mock->createExt.handle);
112     EXPECT_EQ(size, mock->createExt.size);
113 
114     EXPECT_EQ(1u, mock->numRegions);
115     auto memRegions = mock->memRegions;
116     EXPECT_EQ(I915_MEMORY_CLASS_DEVICE, memRegions.memory_class);
117     EXPECT_EQ(0u, memRegions.memory_instance);
118 
119     EXPECT_EQ(gpuAddress, bo->peekAddress());
120     EXPECT_EQ(size, bo->peekSize());
121 }
122 
HWTEST2_F(DrmMemoryManagerLocalMemoryTest,givenMultiRootDeviceEnvironmentAndMemoryInfoWhenCreateMultiGraphicsAllocationThenImportAndExportIoctlAreUsed,NonDefaultIoctlsSupported)123 HWTEST2_F(DrmMemoryManagerLocalMemoryTest, givenMultiRootDeviceEnvironmentAndMemoryInfoWhenCreateMultiGraphicsAllocationThenImportAndExportIoctlAreUsed, NonDefaultIoctlsSupported) {
124     uint32_t rootDevicesNumber = 3u;
125     MultiGraphicsAllocation multiGraphics(rootDevicesNumber);
126     std::vector<uint32_t> rootDeviceIndices;
127     auto osInterface = executionEnvironment->rootDeviceEnvironments[0]->osInterface.release();
128 
129     executionEnvironment->prepareRootDeviceEnvironments(rootDevicesNumber);
130     for (uint32_t i = 0; i < rootDevicesNumber; i++) {
131         executionEnvironment->rootDeviceEnvironments[i]->setHwInfo(defaultHwInfo.get());
132         auto mock = new DrmTipMock(*executionEnvironment->rootDeviceEnvironments[i]);
133 
134         MemoryRegion regionInfo[2] = {};
135         regionInfo[0].region = {I915_MEMORY_CLASS_SYSTEM, 0};
136         regionInfo[1].region = {I915_MEMORY_CLASS_DEVICE, 0};
137 
138         mock->memoryInfo.reset(new MemoryInfo(regionInfo, 2));
139         mock->ioctlCallsCount = 0;
140         executionEnvironment->rootDeviceEnvironments[i]->osInterface = std::make_unique<OSInterface>();
141         executionEnvironment->rootDeviceEnvironments[i]->osInterface->setDriverModel(std::unique_ptr<DriverModel>(mock));
142         executionEnvironment->rootDeviceEnvironments[i]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*mock, 0u);
143 
144         rootDeviceIndices.push_back(i);
145     }
146     auto memoryManager = std::make_unique<TestedDrmMemoryManager>(true, false, false, *executionEnvironment);
147 
148     size_t size = 4096u;
149     AllocationProperties properties(rootDeviceIndex, true, size, GraphicsAllocation::AllocationType::BUFFER_HOST_MEMORY, false, {});
150 
151     static_cast<DrmTipMock *>(executionEnvironment->rootDeviceEnvironments[0]->osInterface->getDriverModel()->as<Drm>())->outputFd = 7;
152 
153     auto ptr = memoryManager->createMultiGraphicsAllocationInSystemMemoryPool(rootDeviceIndices, properties, multiGraphics);
154 
155     EXPECT_NE(ptr, nullptr);
156     EXPECT_NE(static_cast<DrmAllocation *>(multiGraphics.getDefaultGraphicsAllocation())->getMmapPtr(), nullptr);
157     for (uint32_t i = 0; i < rootDevicesNumber; i++) {
158         if (i != 0) {
159             EXPECT_EQ(static_cast<DrmTipMock *>(executionEnvironment->rootDeviceEnvironments[i]->osInterface->getDriverModel()->as<Drm>())->inputFd, 7);
160         }
161         EXPECT_NE(multiGraphics.getGraphicsAllocation(i), nullptr);
162         memoryManager->freeGraphicsMemory(multiGraphics.getGraphicsAllocation(i));
163     }
164 
165     executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(osInterface);
166 }
167 
TEST_F(DrmMemoryManagerLocalMemoryTest,givenMultiRootDeviceEnvironmentAndMemoryInfoWhenCreateMultiGraphicsAllocationAndImportFailsThenNullptrIsReturned)168 TEST_F(DrmMemoryManagerLocalMemoryTest, givenMultiRootDeviceEnvironmentAndMemoryInfoWhenCreateMultiGraphicsAllocationAndImportFailsThenNullptrIsReturned) {
169     uint32_t rootDevicesNumber = 3u;
170     MultiGraphicsAllocation multiGraphics(rootDevicesNumber);
171     std::vector<uint32_t> rootDeviceIndices;
172     auto osInterface = executionEnvironment->rootDeviceEnvironments[0]->osInterface.release();
173 
174     executionEnvironment->prepareRootDeviceEnvironments(rootDevicesNumber);
175     for (uint32_t i = 0; i < rootDevicesNumber; i++) {
176         executionEnvironment->rootDeviceEnvironments[i]->setHwInfo(defaultHwInfo.get());
177         auto mock = new DrmTipMock(*executionEnvironment->rootDeviceEnvironments[i]);
178 
179         MemoryRegion regionInfo[2] = {};
180         regionInfo[0].region = {I915_MEMORY_CLASS_SYSTEM, 0};
181         regionInfo[1].region = {I915_MEMORY_CLASS_DEVICE, 0};
182 
183         mock->memoryInfo.reset(new MemoryInfo(regionInfo, 2));
184         mock->ioctlCallsCount = 0;
185         mock->fdToHandleRetVal = -1;
186         executionEnvironment->rootDeviceEnvironments[i]->osInterface = std::make_unique<OSInterface>();
187         executionEnvironment->rootDeviceEnvironments[i]->osInterface->setDriverModel(std::unique_ptr<DriverModel>(mock));
188         executionEnvironment->rootDeviceEnvironments[i]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*mock, 0u);
189 
190         rootDeviceIndices.push_back(i);
191     }
192     auto memoryManager = std::make_unique<TestedDrmMemoryManager>(true, false, false, *executionEnvironment);
193 
194     size_t size = 4096u;
195     AllocationProperties properties(rootDeviceIndex, true, size, GraphicsAllocation::AllocationType::BUFFER_HOST_MEMORY, false, {});
196 
197     auto ptr = memoryManager->createMultiGraphicsAllocationInSystemMemoryPool(rootDeviceIndices, properties, multiGraphics);
198 
199     EXPECT_EQ(ptr, nullptr);
200 
201     executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(osInterface);
202 }
203 
204 using DrmMemoryManagerUsmSharedHandleTest = DrmMemoryManagerLocalMemoryTest;
205 
TEST_F(DrmMemoryManagerUsmSharedHandleTest,givenDrmMemoryManagerAndOsHandleWhenCreateIsCalledWithBufferHostMemoryAllocationTypeThenGraphicsAllocationIsReturned)206 TEST_F(DrmMemoryManagerUsmSharedHandleTest, givenDrmMemoryManagerAndOsHandleWhenCreateIsCalledWithBufferHostMemoryAllocationTypeThenGraphicsAllocationIsReturned) {
207     osHandle handle = 1u;
208     this->mock->outputHandle = 2u;
209     size_t size = 4096u;
210     AllocationProperties properties(rootDeviceIndex, false, size, GraphicsAllocation::AllocationType::BUFFER_HOST_MEMORY, false, {});
211 
212     auto graphicsAllocation = memoryManager->createGraphicsAllocationFromSharedHandle(handle, properties, false, true);
213     ASSERT_NE(nullptr, graphicsAllocation);
214 
215     EXPECT_EQ(this->mock->inputFd, (int)handle);
216     EXPECT_EQ(this->mock->setTilingHandle, 0u);
217 
218     DrmAllocation *drmAllocation = static_cast<DrmAllocation *>(graphicsAllocation);
219     auto bo = drmAllocation->getBO();
220     EXPECT_EQ(bo->peekHandle(), (int)this->mock->outputHandle);
221     EXPECT_EQ(1u, bo->getRefCount());
222     EXPECT_EQ(size, bo->peekSize());
223 
224     memoryManager->freeGraphicsMemory(graphicsAllocation);
225 }
226 
TEST_F(DrmMemoryManagerUsmSharedHandleTest,givenMultiRootDeviceEnvironmentAndMemoryInfoWhenCreateMultiGraphicsAllocationAndImportFailsThenNullptrIsReturned)227 TEST_F(DrmMemoryManagerUsmSharedHandleTest, givenMultiRootDeviceEnvironmentAndMemoryInfoWhenCreateMultiGraphicsAllocationAndImportFailsThenNullptrIsReturned) {
228     uint32_t rootDevicesNumber = 1u;
229     uint32_t rootDeviceIndex = 0u;
230     MultiGraphicsAllocation multiGraphics(rootDevicesNumber);
231     std::vector<uint32_t> rootDeviceIndices;
232     auto osInterface = executionEnvironment->rootDeviceEnvironments[0]->osInterface.release();
233 
234     executionEnvironment->prepareRootDeviceEnvironments(rootDevicesNumber);
235     executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->setHwInfo(defaultHwInfo.get());
236     auto mock = new DrmTipMock(*executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]);
237 
238     MemoryRegion regionInfo[2] = {};
239     regionInfo[0].region = {I915_MEMORY_CLASS_SYSTEM, 0};
240     regionInfo[1].region = {I915_MEMORY_CLASS_DEVICE, 0};
241 
242     mock->memoryInfo.reset(new MemoryInfo(regionInfo, 2));
243     mock->ioctlCallsCount = 0;
244     mock->fdToHandleRetVal = -1;
245     executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->osInterface = std::make_unique<OSInterface>();
246     executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->osInterface->setDriverModel(std::unique_ptr<DriverModel>(mock));
247     executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*mock, 0u);
248 
249     rootDeviceIndices.push_back(rootDeviceIndex);
250 
251     auto memoryManager = std::make_unique<TestedDrmMemoryManager>(true, false, false, *executionEnvironment);
252 
253     size_t size = 4096u;
254     AllocationProperties properties(rootDeviceIndex, true, size, GraphicsAllocation::AllocationType::BUFFER_HOST_MEMORY, false, {});
255 
256     auto ptr = memoryManager->createUSMHostAllocationFromSharedHandle(1, properties, false);
257 
258     EXPECT_EQ(ptr, nullptr);
259 
260     executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(osInterface);
261 }
262 
TEST_F(DrmMemoryManagerLocalMemoryTest,givenMultiRootDeviceEnvironmentAndNoMemoryInfoWhenCreateMultiGraphicsAllocationThenOldPathIsUsed)263 TEST_F(DrmMemoryManagerLocalMemoryTest, givenMultiRootDeviceEnvironmentAndNoMemoryInfoWhenCreateMultiGraphicsAllocationThenOldPathIsUsed) {
264     uint32_t rootDevicesNumber = 3u;
265     MultiGraphicsAllocation multiGraphics(rootDevicesNumber);
266     std::vector<uint32_t> rootDeviceIndices;
267     auto osInterface = executionEnvironment->rootDeviceEnvironments[0]->osInterface.release();
268 
269     executionEnvironment->prepareRootDeviceEnvironments(rootDevicesNumber);
270     for (uint32_t i = 0; i < rootDevicesNumber; i++) {
271         executionEnvironment->rootDeviceEnvironments[i]->setHwInfo(defaultHwInfo.get());
272         auto mock = new DrmTipMock(*executionEnvironment->rootDeviceEnvironments[i]);
273 
274         mock->memoryInfo.reset(nullptr);
275         mock->ioctlCallsCount = 0;
276         mock->fdToHandleRetVal = -1;
277         executionEnvironment->rootDeviceEnvironments[i]->osInterface = std::make_unique<OSInterface>();
278         executionEnvironment->rootDeviceEnvironments[i]->osInterface->setDriverModel(std::unique_ptr<DriverModel>(mock));
279         executionEnvironment->rootDeviceEnvironments[i]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*mock, 0u);
280 
281         rootDeviceIndices.push_back(i);
282     }
283     auto memoryManager = std::make_unique<TestedDrmMemoryManager>(true, false, false, *executionEnvironment);
284 
285     size_t size = 4096u;
286     AllocationProperties properties(rootDeviceIndex, true, size, GraphicsAllocation::AllocationType::BUFFER_HOST_MEMORY, false, {});
287 
288     auto ptr = memoryManager->createMultiGraphicsAllocationInSystemMemoryPool(rootDeviceIndices, properties, multiGraphics);
289 
290     EXPECT_NE(ptr, nullptr);
291 
292     EXPECT_EQ(static_cast<DrmAllocation *>(multiGraphics.getDefaultGraphicsAllocation())->getMmapPtr(), nullptr);
293     for (uint32_t i = 0; i < rootDevicesNumber; i++) {
294         EXPECT_NE(multiGraphics.getGraphicsAllocation(i), nullptr);
295         memoryManager->freeGraphicsMemory(multiGraphics.getGraphicsAllocation(i));
296     }
297 
298     executionEnvironment->rootDeviceEnvironments[0]->osInterface.reset(osInterface);
299 }
300 
HWTEST2_F(DrmMemoryManagerLocalMemoryTest,givenMemoryInfoWhenAllocateWithAlignmentThenGemCreateExtIsUsed,NonDefaultIoctlsSupported)301 HWTEST2_F(DrmMemoryManagerLocalMemoryTest, givenMemoryInfoWhenAllocateWithAlignmentThenGemCreateExtIsUsed, NonDefaultIoctlsSupported) {
302     DebugManagerStateRestore restorer;
303     DebugManager.flags.EnableBOMmapCreate.set(-1);
304 
305     MemoryRegion regionInfo[2] = {};
306     regionInfo[0].region = {I915_MEMORY_CLASS_SYSTEM, 0};
307     regionInfo[1].region = {I915_MEMORY_CLASS_DEVICE, 0};
308 
309     mock->memoryInfo.reset(new MemoryInfo(regionInfo, 2));
310     mock->ioctlCallsCount = 0;
311 
312     AllocationData allocationData;
313     allocationData.size = MemoryConstants::pageSize64k;
314 
315     auto allocation = memoryManager->allocateGraphicsMemoryWithAlignment(allocationData);
316 
317     EXPECT_NE(allocation, nullptr);
318     EXPECT_NE(allocation->getMmapPtr(), nullptr);
319     EXPECT_NE(allocation->getMmapSize(), 0u);
320     EXPECT_EQ(allocation->getAllocationOffset(), 0u);
321     EXPECT_EQ(1u, mock->createExt.handle);
322 
323     memoryManager->freeGraphicsMemory(allocation);
324 }
325 
TEST_F(DrmMemoryManagerLocalMemoryTest,givenMemoryInfoAndNotUseObjectMmapPropertyWhenAllocateWithAlignmentThenUserptrIsUsed)326 TEST_F(DrmMemoryManagerLocalMemoryTest, givenMemoryInfoAndNotUseObjectMmapPropertyWhenAllocateWithAlignmentThenUserptrIsUsed) {
327     DebugManagerStateRestore restorer;
328     DebugManager.flags.EnableBOMmapCreate.set(0);
329 
330     MemoryRegion regionInfo[2] = {};
331     regionInfo[0].region = {I915_MEMORY_CLASS_SYSTEM, 0};
332     regionInfo[1].region = {I915_MEMORY_CLASS_DEVICE, 0};
333 
334     mock->memoryInfo.reset(new MemoryInfo(regionInfo, 2));
335     mock->mmapOffsetRetVal = -1;
336 
337     AllocationData allocationData;
338     allocationData.size = MemoryConstants::pageSize64k;
339     allocationData.useMmapObject = false;
340 
341     auto allocation = memoryManager->allocateGraphicsMemoryWithAlignment(allocationData);
342 
343     EXPECT_NE(allocation, nullptr);
344     EXPECT_EQ(static_cast<int>(mock->returnHandle), allocation->getBO()->peekHandle() + 1);
345 
346     memoryManager->freeGraphicsMemory(allocation);
347 }
348 
TEST_F(DrmMemoryManagerLocalMemoryTest,givenMemoryInfoAndFailedMmapOffsetWhenAllocateWithAlignmentThenNullptr)349 TEST_F(DrmMemoryManagerLocalMemoryTest, givenMemoryInfoAndFailedMmapOffsetWhenAllocateWithAlignmentThenNullptr) {
350     DebugManagerStateRestore restorer;
351     DebugManager.flags.EnableBOMmapCreate.set(-1);
352 
353     MemoryRegion regionInfo[2] = {};
354     regionInfo[0].region = {I915_MEMORY_CLASS_SYSTEM, 0};
355     regionInfo[1].region = {I915_MEMORY_CLASS_DEVICE, 0};
356 
357     mock->memoryInfo.reset(new MemoryInfo(regionInfo, 2));
358     mock->mmapOffsetRetVal = -1;
359 
360     AllocationData allocationData;
361     allocationData.size = MemoryConstants::pageSize64k;
362 
363     auto allocation = memoryManager->allocateGraphicsMemoryWithAlignment(allocationData);
364 
365     EXPECT_EQ(allocation, nullptr);
366     mock->mmapOffsetRetVal = 0;
367 }
368 
TEST_F(DrmMemoryManagerLocalMemoryTest,givenMemoryInfoAndDisabledMmapBOCreationtWhenAllocateWithAlignmentThenUserptrIsUsed)369 TEST_F(DrmMemoryManagerLocalMemoryTest, givenMemoryInfoAndDisabledMmapBOCreationtWhenAllocateWithAlignmentThenUserptrIsUsed) {
370     DebugManagerStateRestore restorer;
371     DebugManager.flags.EnableBOMmapCreate.set(0);
372 
373     MemoryRegion regionInfo[2] = {};
374     regionInfo[0].region = {I915_MEMORY_CLASS_SYSTEM, 0};
375     regionInfo[1].region = {I915_MEMORY_CLASS_DEVICE, 0};
376 
377     mock->memoryInfo.reset(new MemoryInfo(regionInfo, 2));
378     mock->mmapOffsetRetVal = -1;
379 
380     AllocationData allocationData;
381     allocationData.size = MemoryConstants::pageSize64k;
382 
383     auto allocation = memoryManager->allocateGraphicsMemoryWithAlignment(allocationData);
384 
385     EXPECT_NE(allocation, nullptr);
386     EXPECT_EQ(static_cast<int>(mock->returnHandle), allocation->getBO()->peekHandle() + 1);
387 
388     memoryManager->freeGraphicsMemory(allocation);
389 }
390 
TEST_F(DrmMemoryManagerLocalMemoryTest,givenMemoryInfoAndFailedGemCreateExtWhenAllocateWithAlignmentThenNullptr)391 TEST_F(DrmMemoryManagerLocalMemoryTest, givenMemoryInfoAndFailedGemCreateExtWhenAllocateWithAlignmentThenNullptr) {
392     DebugManagerStateRestore restorer;
393     DebugManager.flags.EnableBOMmapCreate.set(-1);
394 
395     MemoryRegion regionInfo[2] = {};
396     regionInfo[0].region = {I915_MEMORY_CLASS_SYSTEM, 0};
397     regionInfo[1].region = {I915_MEMORY_CLASS_DEVICE, 0};
398 
399     mock->memoryInfo.reset(new MemoryInfo(regionInfo, 2));
400     mock->gemCreateExtRetVal = -1;
401 
402     AllocationData allocationData;
403     allocationData.size = MemoryConstants::pageSize64k;
404 
405     auto allocation = memoryManager->allocateGraphicsMemoryWithAlignment(allocationData);
406 
407     EXPECT_EQ(allocation, nullptr);
408     mock->gemCreateExtRetVal = 0;
409 }
410 
411 class DrmMemoryManagerLocalMemoryMemoryBankMock : public TestedDrmMemoryManager {
412   public:
DrmMemoryManagerLocalMemoryMemoryBankMock(bool enableLocalMemory,bool allowForcePin,bool validateHostPtrMemory,ExecutionEnvironment & executionEnvironment)413     DrmMemoryManagerLocalMemoryMemoryBankMock(bool enableLocalMemory,
414                                               bool allowForcePin,
415                                               bool validateHostPtrMemory,
416                                               ExecutionEnvironment &executionEnvironment) : TestedDrmMemoryManager(enableLocalMemory, allowForcePin, validateHostPtrMemory, executionEnvironment) {
417     }
418 
createBufferObjectInMemoryRegion(Drm * drm,uint64_t gpuAddress,size_t size,uint32_t memoryBanks,size_t maxOsContextCount)419     BufferObject *createBufferObjectInMemoryRegion(Drm *drm,
420                                                    uint64_t gpuAddress,
421                                                    size_t size,
422                                                    uint32_t memoryBanks,
423                                                    size_t maxOsContextCount) override {
424         memoryBankIsOne = (memoryBanks == 1) ? true : false;
425         return nullptr;
426     }
427 
428     bool memoryBankIsOne = false;
429 };
430 
431 class DrmMemoryManagerLocalMemoryMemoryBankTest : public ::testing::Test {
432   public:
433     DrmTipMock *mock;
434 
SetUp()435     void SetUp() override {
436         const bool localMemoryEnabled = true;
437         executionEnvironment = new ExecutionEnvironment;
438         executionEnvironment->prepareRootDeviceEnvironments(1);
439         executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->setHwInfo(defaultHwInfo.get());
440         mock = new DrmTipMock(*executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]);
441         mock->memoryInfo.reset(new MockMemoryInfo());
442         executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->osInterface = std::make_unique<OSInterface>();
443         executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->osInterface->setDriverModel(std::unique_ptr<DriverModel>(mock));
444         executionEnvironment->rootDeviceEnvironments[rootDeviceIndex]->memoryOperationsInterface = DrmMemoryOperationsHandler::create(*mock, 0u);
445 
446         device.reset(MockDevice::createWithExecutionEnvironment<MockDevice>(defaultHwInfo.get(),
447                                                                             executionEnvironment,
448                                                                             rootDeviceIndex));
449         memoryManager = std::make_unique<DrmMemoryManagerLocalMemoryMemoryBankMock>(localMemoryEnabled,
450                                                                                     false,
451                                                                                     false,
452                                                                                     *executionEnvironment);
453     }
454 
455   protected:
456     ExecutionEnvironment *executionEnvironment = nullptr;
457     std::unique_ptr<MockDevice> device;
458     std::unique_ptr<DrmMemoryManagerLocalMemoryMemoryBankMock> memoryManager;
459     const uint32_t rootDeviceIndex = 0u;
460 };
461 
TEST_F(DrmMemoryManagerLocalMemoryMemoryBankTest,givenDeviceMemoryWhenGraphicsAllocationInDevicePoolIsAllocatedThenMemoryBankIsSetToOne)462 TEST_F(DrmMemoryManagerLocalMemoryMemoryBankTest, givenDeviceMemoryWhenGraphicsAllocationInDevicePoolIsAllocatedThenMemoryBankIsSetToOne) {
463     MemoryManager::AllocationStatus status = MemoryManager::AllocationStatus::Success;
464     AllocationData allocData;
465     allocData.allFlags = 0;
466     allocData.size = MemoryConstants::pageSize;
467     allocData.flags.useSystemMemory = false;
468     allocData.type = GraphicsAllocation::AllocationType::BUFFER;
469     allocData.rootDeviceIndex = rootDeviceIndex;
470     allocData.storageInfo.memoryBanks = 1u;
471     memoryManager->allocateGraphicsMemoryInDevicePool(allocData, status);
472     EXPECT_TRUE(memoryManager->memoryBankIsOne);
473 }
474 
HWTEST2_F(DrmMemoryManagerLocalMemoryTest,givenCpuAccessRequiredWhenAllocatingInDevicePoolThenAllocationIsLocked,NonDefaultIoctlsSupported)475 HWTEST2_F(DrmMemoryManagerLocalMemoryTest, givenCpuAccessRequiredWhenAllocatingInDevicePoolThenAllocationIsLocked, NonDefaultIoctlsSupported) {
476     MemoryManager::AllocationStatus status = MemoryManager::AllocationStatus::Success;
477     AllocationData allocData;
478     allocData.allFlags = 0;
479     allocData.size = MemoryConstants::pageSize;
480     allocData.flags.requiresCpuAccess = true;
481     allocData.flags.allocateMemory = true;
482     allocData.type = GraphicsAllocation::AllocationType::BUFFER;
483     allocData.rootDeviceIndex = rootDeviceIndex;
484 
485     auto allocation = memoryManager->allocateGraphicsMemoryInDevicePool(allocData, status);
486     ASSERT_NE(nullptr, allocation);
487     EXPECT_EQ(MemoryManager::AllocationStatus::Success, status);
488     EXPECT_EQ(MemoryPool::LocalMemory, allocation->getMemoryPool());
489     EXPECT_TRUE(allocation->isLocked());
490     EXPECT_NE(nullptr, allocation->getLockedPtr());
491     EXPECT_NE(nullptr, allocation->getUnderlyingBuffer());
492     EXPECT_NE(0u, allocation->getGpuAddress());
493 
494     memoryManager->freeGraphicsMemory(allocation);
495 }
496 
HWTEST2_F(DrmMemoryManagerLocalMemoryTest,givenWriteCombinedAllocationWhenAllocatingInDevicePoolThenAllocationIsLockedAndLockedPtrIsUsedAsGpuAddress,NonDefaultIoctlsSupported)497 HWTEST2_F(DrmMemoryManagerLocalMemoryTest, givenWriteCombinedAllocationWhenAllocatingInDevicePoolThenAllocationIsLockedAndLockedPtrIsUsedAsGpuAddress, NonDefaultIoctlsSupported) {
498     MemoryManager::AllocationStatus status = MemoryManager::AllocationStatus::Success;
499     AllocationData allocData{};
500     allocData.size = MemoryConstants::pageSize;
501     allocData.type = GraphicsAllocation::AllocationType::WRITE_COMBINED;
502     allocData.rootDeviceIndex = rootDeviceIndex;
503     auto sizeAligned = alignUp(allocData.size + MemoryConstants::pageSize64k, 2 * MemoryConstants::megaByte) + 2 * MemoryConstants::megaByte;
504 
505     auto allocation = memoryManager->allocateGraphicsMemoryInDevicePool(allocData, status);
506     EXPECT_NE(nullptr, allocation);
507     EXPECT_EQ(MemoryManager::AllocationStatus::Success, status);
508     EXPECT_EQ(MemoryPool::LocalMemory, allocation->getMemoryPool());
509     EXPECT_TRUE(allocation->isLocked());
510     EXPECT_NE(nullptr, allocation->getLockedPtr());
511 
512     EXPECT_EQ(allocation->getLockedPtr(), allocation->getUnderlyingBuffer());
513     EXPECT_EQ(allocation->getLockedPtr(), reinterpret_cast<void *>(allocation->getGpuAddress()));
514     EXPECT_EQ(sizeAligned, allocation->getUnderlyingBufferSize());
515 
516     EXPECT_EQ(0u, allocation->getReservedAddressSize());
517 
518     auto cpuAddress = allocation->getLockedPtr();
519     auto alignedCpuAddress = alignDown(cpuAddress, 2 * MemoryConstants::megaByte);
520     auto offset = ptrDiff(cpuAddress, alignedCpuAddress);
521     EXPECT_EQ(offset, allocation->getAllocationOffset());
522 
523     auto drmAllocation = static_cast<DrmAllocation *>(allocation);
524     auto bo = drmAllocation->getBO();
525     EXPECT_NE(nullptr, bo);
526     EXPECT_EQ(reinterpret_cast<uint64_t>(cpuAddress), bo->peekAddress());
527     EXPECT_EQ(sizeAligned, bo->peekSize());
528 
529     memoryManager->freeGraphicsMemory(allocation);
530 }
531 
HWTEST2_F(DrmMemoryManagerLocalMemoryTest,givenSupportedTypeWhenAllocatingInDevicePoolThenSuccessStatusAndNonNullPtrIsReturned,NonDefaultIoctlsSupported)532 HWTEST2_F(DrmMemoryManagerLocalMemoryTest, givenSupportedTypeWhenAllocatingInDevicePoolThenSuccessStatusAndNonNullPtrIsReturned, NonDefaultIoctlsSupported) {
533     MemoryManager::AllocationStatus status = MemoryManager::AllocationStatus::Success;
534     AllocationData allocData;
535     allocData.allFlags = 0;
536     allocData.size = MemoryConstants::pageSize;
537     allocData.flags.allocateMemory = true;
538     allocData.rootDeviceIndex = rootDeviceIndex;
539     ImageDescriptor imgDesc = {};
540     imgDesc.imageType = ImageType::Image2D;
541     imgDesc.imageWidth = MemoryConstants::pageSize;
542     imgDesc.imageHeight = MemoryConstants::pageSize;
543     auto imgInfo = MockGmm::initImgInfo(imgDesc, 0, nullptr);
544 
545     bool resource48Bit[] = {true, false};
546     GraphicsAllocation::AllocationType supportedTypes[] = {GraphicsAllocation::AllocationType::BUFFER,
547                                                            GraphicsAllocation::AllocationType::IMAGE,
548                                                            GraphicsAllocation::AllocationType::COMMAND_BUFFER,
549                                                            GraphicsAllocation::AllocationType::LINEAR_STREAM,
550                                                            GraphicsAllocation::AllocationType::INDIRECT_OBJECT_HEAP,
551                                                            GraphicsAllocation::AllocationType::TIMESTAMP_PACKET_TAG_BUFFER,
552                                                            GraphicsAllocation::AllocationType::INTERNAL_HEAP,
553                                                            GraphicsAllocation::AllocationType::KERNEL_ISA,
554                                                            GraphicsAllocation::AllocationType::SVM_GPU};
555     for (auto res48bit : resource48Bit) {
556         for (auto supportedType : supportedTypes) {
557             allocData.type = supportedType;
558             allocData.imgInfo = (GraphicsAllocation::AllocationType::IMAGE == supportedType) ? &imgInfo : nullptr;
559             allocData.hostPtr = (GraphicsAllocation::AllocationType::SVM_GPU == supportedType) ? ::alignedMalloc(allocData.size, 4096) : nullptr;
560 
561             switch (supportedType) {
562             case GraphicsAllocation::AllocationType::IMAGE:
563             case GraphicsAllocation::AllocationType::INDIRECT_OBJECT_HEAP:
564             case GraphicsAllocation::AllocationType::INTERNAL_HEAP:
565             case GraphicsAllocation::AllocationType::KERNEL_ISA:
566                 allocData.flags.resource48Bit = true;
567                 break;
568             default:
569                 allocData.flags.resource48Bit = res48bit;
570             }
571 
572             auto allocation = memoryManager->allocateGraphicsMemoryInDevicePool(allocData, status);
573             ASSERT_NE(nullptr, allocation);
574             EXPECT_EQ(MemoryManager::AllocationStatus::Success, status);
575 
576             auto gpuAddress = allocation->getGpuAddress();
577             if (allocation->getAllocationType() == GraphicsAllocation::AllocationType::SVM_GPU) {
578                 if (!memoryManager->isLimitedRange(0)) {
579                     EXPECT_LT(GmmHelper::canonize(memoryManager->getGfxPartition(0)->getHeapBase(HeapIndex::HEAP_SVM)), gpuAddress);
580                     EXPECT_GT(GmmHelper::canonize(memoryManager->getGfxPartition(0)->getHeapLimit(HeapIndex::HEAP_SVM)), gpuAddress);
581                 }
582             } else if (memoryManager->heapAssigner.useInternal32BitHeap(allocation->getAllocationType())) {
583                 EXPECT_LT(GmmHelper::canonize(memoryManager->getGfxPartition(0)->getHeapBase(HeapIndex::HEAP_INTERNAL_DEVICE_MEMORY)), gpuAddress);
584                 EXPECT_GT(GmmHelper::canonize(memoryManager->getGfxPartition(0)->getHeapLimit(HeapIndex::HEAP_INTERNAL_DEVICE_MEMORY)), gpuAddress);
585             } else {
586                 const bool prefer2MBAlignment = allocation->getUnderlyingBufferSize() >= 2 * MemoryConstants::megaByte;
587 
588                 auto heap = HeapIndex::HEAP_STANDARD64KB;
589                 if (prefer2MBAlignment) {
590                     heap = HeapIndex::HEAP_STANDARD2MB;
591                 } else if (memoryManager->getGfxPartition(0)->getHeapLimit(HeapIndex::HEAP_EXTENDED) > 0 && !allocData.flags.resource48Bit) {
592                     heap = HeapIndex::HEAP_EXTENDED;
593                 }
594 
595                 EXPECT_LT(GmmHelper::canonize(memoryManager->getGfxPartition(0)->getHeapBase(heap)), gpuAddress);
596                 EXPECT_GT(GmmHelper::canonize(memoryManager->getGfxPartition(0)->getHeapLimit(heap)), gpuAddress);
597             }
598 
599             memoryManager->freeGraphicsMemory(allocation);
600             if (GraphicsAllocation::AllocationType::SVM_GPU == supportedType) {
601                 ::alignedFree(const_cast<void *>(allocData.hostPtr));
602             }
603         }
604     }
605 }
606 
TEST_F(DrmMemoryManagerLocalMemoryTest,givenDrmMemoryManagerWithLocalMemoryWhenLockResourceIsCalledOnNullBufferObjectThenReturnNullPtr)607 TEST_F(DrmMemoryManagerLocalMemoryTest, givenDrmMemoryManagerWithLocalMemoryWhenLockResourceIsCalledOnNullBufferObjectThenReturnNullPtr) {
608     auto ptr = memoryManager->lockResourceInLocalMemoryImpl(nullptr);
609     EXPECT_EQ(nullptr, ptr);
610 
611     memoryManager->unlockResourceInLocalMemoryImpl(nullptr);
612 }
613 
TEST_F(DrmMemoryManagerLocalMemoryWithCustomMockTest,givenDrmMemoryManagerWithLocalMemoryWhenLockResourceIsCalledOnBufferObjectThenReturnPtr)614 TEST_F(DrmMemoryManagerLocalMemoryWithCustomMockTest, givenDrmMemoryManagerWithLocalMemoryWhenLockResourceIsCalledOnBufferObjectThenReturnPtr) {
615     BufferObject bo(mock, 1, 1024, 0);
616 
617     DrmAllocation drmAllocation(0, GraphicsAllocation::AllocationType::UNKNOWN, &bo, nullptr, 0u, 0u, MemoryPool::LocalMemory);
618     EXPECT_EQ(&bo, drmAllocation.getBO());
619 
620     auto ptr = memoryManager->lockResourceInLocalMemoryImpl(&bo);
621     EXPECT_NE(nullptr, ptr);
622     EXPECT_EQ(ptr, bo.peekLockedAddress());
623 
624     memoryManager->unlockResourceInLocalMemoryImpl(&bo);
625     EXPECT_EQ(nullptr, bo.peekLockedAddress());
626 }
627 
628 using DrmMemoryManagerFailInjectionTest = Test<DrmMemoryManagerFixtureImpl>;
629 
HWTEST2_F(DrmMemoryManagerFailInjectionTest,givenEnabledLocalMemoryWhenNewFailsThenAllocateInDevicePoolReturnsStatusErrorAndNullallocation,NonDefaultIoctlsSupported)630 HWTEST2_F(DrmMemoryManagerFailInjectionTest, givenEnabledLocalMemoryWhenNewFailsThenAllocateInDevicePoolReturnsStatusErrorAndNullallocation, NonDefaultIoctlsSupported) {
631     mock->ioctl_expected.total = -1; //don't care
632     class MockGfxPartition : public GfxPartition {
633       public:
634         MockGfxPartition() : GfxPartition(reservedCpuAddressRange) {
635             init(defaultHwInfo->capabilityTable.gpuAddressSpace, getSizeToReserve(), 0, 1);
636         }
637         ~MockGfxPartition() override {
638             for (const auto &heap : heaps) {
639                 auto mockHeap = static_cast<const MockHeap *>(&heap);
640                 if (defaultHwInfo->capabilityTable.gpuAddressSpace != MemoryConstants::max36BitAddress && mockHeap->getSize() > 0) {
641                     EXPECT_EQ(0u, mockHeap->alloc->getUsedSize());
642                 }
643             }
644         }
645         struct MockHeap : Heap {
646             using Heap::alloc;
647         };
648         OSMemory::ReservedCpuAddressRange reservedCpuAddressRange;
649     };
650     TestedDrmMemoryManager testedMemoryManager(true, false, true, *executionEnvironment);
651     testedMemoryManager.overrideGfxPartition(new MockGfxPartition);
652 
653     InjectedFunction method = [&](size_t failureIndex) {
654         MemoryManager::AllocationStatus status = MemoryManager::AllocationStatus::Success;
655         AllocationData allocData;
656         allocData.allFlags = 0;
657         allocData.size = MemoryConstants::pageSize;
658         allocData.flags.allocateMemory = true;
659         allocData.type = GraphicsAllocation::AllocationType::BUFFER;
660         allocData.rootDeviceIndex = rootDeviceIndex;
661 
662         auto allocation = testedMemoryManager.allocateGraphicsMemoryInDevicePool(allocData, status);
663 
664         if (MemoryManagement::nonfailingAllocation != failureIndex) {
665             EXPECT_EQ(nullptr, allocation);
666             EXPECT_EQ(MemoryManager::AllocationStatus::Error, status);
667         } else {
668             EXPECT_NE(nullptr, allocation);
669             EXPECT_EQ(MemoryManager::AllocationStatus::Success, status);
670             testedMemoryManager.freeGraphicsMemory(allocation);
671         }
672     };
673 
674     mock->memoryInfo.reset(new MockMemoryInfo());
675     injectFailures(method);
676 }
677 
678 using DrmMemoryManagerCopyMemoryToAllocationTest = DrmMemoryManagerLocalMemoryTest;
679 
680 struct DrmMemoryManagerToTestCopyMemoryToAllocation : public DrmMemoryManager {
681     using DrmMemoryManager::allocateGraphicsMemoryInDevicePool;
DrmMemoryManagerToTestCopyMemoryToAllocationNEO::DrmMemoryManagerToTestCopyMemoryToAllocation682     DrmMemoryManagerToTestCopyMemoryToAllocation(ExecutionEnvironment &executionEnvironment, bool localMemoryEnabled, size_t lockableLocalMemorySize)
683         : DrmMemoryManager(gemCloseWorkerMode::gemCloseWorkerInactive, false, false, executionEnvironment) {
684         std::fill(this->localMemorySupported.begin(), this->localMemorySupported.end(), localMemoryEnabled);
685         lockedLocalMemorySize = lockableLocalMemorySize;
686     }
lockResourceImplNEO::DrmMemoryManagerToTestCopyMemoryToAllocation687     void *lockResourceImpl(GraphicsAllocation &graphicsAllocation) override {
688         if (lockedLocalMemorySize > 0) {
689             lockedLocalMemory.reset(new uint8_t[lockedLocalMemorySize]);
690             return lockedLocalMemory.get();
691         }
692         return nullptr;
693     }
lockResourceInLocalMemoryImplNEO::DrmMemoryManagerToTestCopyMemoryToAllocation694     void *lockResourceInLocalMemoryImpl(BufferObject *bo) override {
695         if (lockedLocalMemorySize > 0) {
696             lockedLocalMemory.reset(new uint8_t[lockedLocalMemorySize]);
697             return lockedLocalMemory.get();
698         }
699         return nullptr;
700     }
unlockResourceInLocalMemoryImplNEO::DrmMemoryManagerToTestCopyMemoryToAllocation701     void unlockResourceInLocalMemoryImpl(BufferObject *bo) override {
702     }
unlockResourceImplNEO::DrmMemoryManagerToTestCopyMemoryToAllocation703     void unlockResourceImpl(GraphicsAllocation &graphicsAllocation) override {
704     }
705     std::unique_ptr<uint8_t[]> lockedLocalMemory;
706     size_t lockedLocalMemorySize = 0;
707 };
708 
HWTEST2_F(DrmMemoryManagerCopyMemoryToAllocationTest,givenDrmMemoryManagerWhenCopyMemoryToAllocationReturnsSuccessThenAllocationIsFilledWithCorrectData,NonDefaultIoctlsSupported)709 HWTEST2_F(DrmMemoryManagerCopyMemoryToAllocationTest, givenDrmMemoryManagerWhenCopyMemoryToAllocationReturnsSuccessThenAllocationIsFilledWithCorrectData, NonDefaultIoctlsSupported) {
710     size_t offset = 3;
711     size_t sourceAllocationSize = MemoryConstants::pageSize;
712     size_t destinationAllocationSize = sourceAllocationSize + offset;
713 
714     DrmMemoryManagerToTestCopyMemoryToAllocation drmMemoryManger(*executionEnvironment, true, destinationAllocationSize);
715     std::vector<uint8_t> dataToCopy(sourceAllocationSize, 1u);
716 
717     AllocationData allocData;
718     allocData.allFlags = 0;
719     allocData.size = destinationAllocationSize;
720     allocData.flags.allocateMemory = true;
721     allocData.type = GraphicsAllocation::AllocationType::KERNEL_ISA;
722     allocData.rootDeviceIndex = rootDeviceIndex;
723     allocData.storageInfo.memoryBanks.set(0, true);
724     MemoryManager::AllocationStatus status = MemoryManager::AllocationStatus::Success;
725     auto allocation = drmMemoryManger.allocateGraphicsMemoryInDevicePool(allocData, status);
726     ASSERT_NE(nullptr, allocation);
727 
728     auto ret = drmMemoryManger.copyMemoryToAllocation(allocation, offset, dataToCopy.data(), dataToCopy.size());
729     EXPECT_TRUE(ret);
730 
731     EXPECT_EQ(0, memcmp(ptrOffset(drmMemoryManger.lockedLocalMemory.get(), offset), dataToCopy.data(), dataToCopy.size()));
732 
733     drmMemoryManger.freeGraphicsMemory(allocation);
734 }
735 
HWTEST2_F(DrmMemoryManagerCopyMemoryToAllocationTest,givenDrmMemoryManagerWhenCopyMemoryToAllocationFailsToLockResourceThenItReturnsFalse,NonDefaultIoctlsSupported)736 HWTEST2_F(DrmMemoryManagerCopyMemoryToAllocationTest, givenDrmMemoryManagerWhenCopyMemoryToAllocationFailsToLockResourceThenItReturnsFalse, NonDefaultIoctlsSupported) {
737     DrmMemoryManagerToTestCopyMemoryToAllocation drmMemoryManger(*executionEnvironment, true, 0);
738     std::vector<uint8_t> dataToCopy(MemoryConstants::pageSize, 1u);
739 
740     AllocationData allocData;
741     allocData.allFlags = 0;
742     allocData.size = dataToCopy.size();
743     allocData.flags.allocateMemory = true;
744     allocData.type = GraphicsAllocation::AllocationType::KERNEL_ISA;
745     allocData.rootDeviceIndex = rootDeviceIndex;
746     allocData.storageInfo.memoryBanks.set(0, true);
747     MemoryManager::AllocationStatus status = MemoryManager::AllocationStatus::Success;
748     auto allocation = drmMemoryManger.allocateGraphicsMemoryInDevicePool(allocData, status);
749     ASSERT_NE(nullptr, allocation);
750 
751     auto ret = drmMemoryManger.copyMemoryToAllocation(allocation, 0, dataToCopy.data(), dataToCopy.size());
752     EXPECT_FALSE(ret);
753 
754     drmMemoryManger.freeGraphicsMemory(allocation);
755 }
756 
TEST_F(DrmMemoryManagerCopyMemoryToAllocationTest,givenDrmMemoryManagerWhenCopyMemoryToAllocationWithCpuPtrThenAllocationIsFilledWithCorrectData)757 TEST_F(DrmMemoryManagerCopyMemoryToAllocationTest, givenDrmMemoryManagerWhenCopyMemoryToAllocationWithCpuPtrThenAllocationIsFilledWithCorrectData) {
758     size_t offset = 3;
759     size_t sourceAllocationSize = MemoryConstants::pageSize;
760     size_t destinationAllocationSize = sourceAllocationSize + offset;
761 
762     DrmMemoryManagerToTestCopyMemoryToAllocation drmMemoryManger(*executionEnvironment, false, 0);
763     std::vector<uint8_t> dataToCopy(sourceAllocationSize, 1u);
764 
765     auto allocation = drmMemoryManger.allocateGraphicsMemoryWithProperties({mockRootDeviceIndex, destinationAllocationSize, GraphicsAllocation::AllocationType::KERNEL_ISA, mockDeviceBitfield});
766     ASSERT_NE(nullptr, allocation);
767 
768     auto ret = drmMemoryManger.copyMemoryToAllocation(allocation, offset, dataToCopy.data(), dataToCopy.size());
769     EXPECT_TRUE(ret);
770 
771     EXPECT_EQ(0, memcmp(ptrOffset(allocation->getUnderlyingBuffer(), offset), dataToCopy.data(), dataToCopy.size()));
772 
773     drmMemoryManger.freeGraphicsMemory(allocation);
774 }
775 
776 using DrmMemoryManagerTestImpl = Test<DrmMemoryManagerFixtureImpl>;
777 
HWTEST2_F(DrmMemoryManagerTestImpl,givenDrmMemoryManagerWhenLockUnlockIsCalledOnAllocationInLocalMemoryThenCallIoctlGemMapOffsetAndReturnLockedPtr,NonDefaultIoctlsSupported)778 HWTEST2_F(DrmMemoryManagerTestImpl, givenDrmMemoryManagerWhenLockUnlockIsCalledOnAllocationInLocalMemoryThenCallIoctlGemMapOffsetAndReturnLockedPtr, NonDefaultIoctlsSupported) {
779     mockExp->ioctlImpl_expected.gemCreateExt = 1;
780     mockExp->ioctl_expected.gemWait = 1;
781     mockExp->ioctl_expected.gemClose = 1;
782     mockExp->ioctl_expected.gemMmapOffset = 1;
783     mockExp->memoryInfo.reset(new MockMemoryInfo());
784 
785     AllocationData allocData;
786     allocData.allFlags = 0;
787     allocData.size = MemoryConstants::pageSize;
788     allocData.flags.allocateMemory = true;
789     allocData.type = GraphicsAllocation::AllocationType::INTERNAL_HEAP;
790     allocData.rootDeviceIndex = rootDeviceIndex;
791     MemoryManager::AllocationStatus status = MemoryManager::AllocationStatus::Success;
792     auto allocation = memoryManager->allocateGraphicsMemoryInDevicePool(allocData, status);
793     ASSERT_NE(nullptr, allocation);
794     EXPECT_EQ(nullptr, allocation->getUnderlyingBuffer());
795     EXPECT_EQ(MemoryPool::LocalMemory, allocation->getMemoryPool());
796 
797     auto ptr = memoryManager->lockResource(allocation);
798     EXPECT_NE(nullptr, ptr);
799 
800     auto drmAllocation = static_cast<DrmAllocation *>(allocation);
801     EXPECT_NE(nullptr, drmAllocation->getBO()->peekLockedAddress());
802 
803     EXPECT_EQ(static_cast<uint32_t>(drmAllocation->getBO()->peekHandle()), mockExp->mmapOffsetHandle);
804     EXPECT_EQ(0u, mockExp->mmapOffsetPad);
805     EXPECT_EQ(0u, mockExp->mmapOffsetExpected);
806     EXPECT_EQ(4u, mockExp->mmapOffsetFlags);
807 
808     memoryManager->unlockResource(allocation);
809     EXPECT_EQ(nullptr, drmAllocation->getBO()->peekLockedAddress());
810 
811     memoryManager->freeGraphicsMemory(allocation);
812 }
813 
TEST_F(DrmMemoryManagerTestImpl,givenDrmMemoryManagerWhenLockUnlockIsCalledOnAllocationInLocalMemoryButFailsOnMmapThenReturnNullPtr)814 TEST_F(DrmMemoryManagerTestImpl, givenDrmMemoryManagerWhenLockUnlockIsCalledOnAllocationInLocalMemoryButFailsOnMmapThenReturnNullPtr) {
815     mockExp->ioctl_expected.gemMmapOffset = 2;
816     this->ioctlResExt = {mockExp->ioctl_cnt.total, -1};
817     mockExp->ioctl_res_ext = &ioctlResExt;
818 
819     BufferObject bo(mockExp, 1, 0, 0);
820     DrmAllocation drmAllocation(0, GraphicsAllocation::AllocationType::UNKNOWN, &bo, nullptr, 0u, 0u, MemoryPool::LocalMemory);
821     EXPECT_NE(nullptr, drmAllocation.getBO());
822 
823     auto ptr = memoryManager->lockResource(&drmAllocation);
824     EXPECT_EQ(nullptr, ptr);
825 
826     memoryManager->unlockResource(&drmAllocation);
827     mockExp->ioctl_res_ext = &mockExp->NONE;
828 }
829 
TEST_F(DrmMemoryManagerTestImpl,givenDrmMemoryManagerWhenLockUnlockIsCalledOnAllocationInLocalMemoryButFailsOnIoctlMmapFunctionOffsetThenReturnNullPtr)830 TEST_F(DrmMemoryManagerTestImpl, givenDrmMemoryManagerWhenLockUnlockIsCalledOnAllocationInLocalMemoryButFailsOnIoctlMmapFunctionOffsetThenReturnNullPtr) {
831     mockExp->ioctl_expected.gemMmapOffset = 2;
832     mockExp->returnIoctlExtraErrorValue = true;
833     mockExp->failOnMmapOffset = true;
834 
835     BufferObject bo(mockExp, 1, 0, 0);
836     DrmAllocation drmAllocation(0, GraphicsAllocation::AllocationType::UNKNOWN, &bo, nullptr, 0u, 0u, MemoryPool::LocalMemory);
837     EXPECT_NE(nullptr, drmAllocation.getBO());
838 
839     auto ptr = memoryManager->lockResource(&drmAllocation);
840     EXPECT_EQ(nullptr, ptr);
841 
842     memoryManager->unlockResource(&drmAllocation);
843     mockExp->ioctl_res_ext = &mockExp->NONE;
844 }
845 
TEST_F(DrmMemoryManagerTestImpl,givenDrmMemoryManagerWhenLockUnlockIsCalledOnAllocationInLocalMemoryButBufferObjectIsNullThenReturnNullPtr)846 TEST_F(DrmMemoryManagerTestImpl, givenDrmMemoryManagerWhenLockUnlockIsCalledOnAllocationInLocalMemoryButBufferObjectIsNullThenReturnNullPtr) {
847     DrmAllocation drmAllocation(0, GraphicsAllocation::AllocationType::UNKNOWN, nullptr, nullptr, 0u, 0u, MemoryPool::LocalMemory);
848 
849     auto ptr = memoryManager->lockResource(&drmAllocation);
850     EXPECT_EQ(nullptr, ptr);
851 
852     memoryManager->unlockResource(&drmAllocation);
853 }
854 
TEST_F(DrmMemoryManagerTestImpl,givenDrmMemoryManagerWhenGetLocalMemorySizeIsCalledForMemoryInfoThenReturnMemoryRegionSize)855 TEST_F(DrmMemoryManagerTestImpl, givenDrmMemoryManagerWhenGetLocalMemorySizeIsCalledForMemoryInfoThenReturnMemoryRegionSize) {
856     MockExecutionEnvironment executionEnvironment;
857     executionEnvironment.rootDeviceEnvironments[0]->osInterface = std::make_unique<OSInterface>();
858     auto drm = new DrmMock(*executionEnvironment.rootDeviceEnvironments[0]);
859     drm->memoryInfo.reset(new MockMemoryInfo());
860     executionEnvironment.rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr<DriverModel>(drm));
861     TestedDrmMemoryManager memoryManager(executionEnvironment);
862 
863     auto memoryInfo = drm->getMemoryInfo();
864     ASSERT_NE(nullptr, memoryInfo);
865     EXPECT_EQ(memoryInfo->getMemoryRegionSize(MemoryBanks::getBankForLocalMemory(0)), memoryManager.getLocalMemorySize(0u, 0xF));
866 }
867 
TEST_F(DrmMemoryManagerTestImpl,givenDrmMemoryManagerWhenGetLocalMemorySizeIsCalledForMemoryInfoAndInvalidDeviceBitfieldThenReturnZero)868 TEST_F(DrmMemoryManagerTestImpl, givenDrmMemoryManagerWhenGetLocalMemorySizeIsCalledForMemoryInfoAndInvalidDeviceBitfieldThenReturnZero) {
869     MockExecutionEnvironment executionEnvironment;
870     executionEnvironment.rootDeviceEnvironments[0]->osInterface = std::make_unique<OSInterface>();
871     auto drm = new DrmMock(*executionEnvironment.rootDeviceEnvironments[0]);
872     drm->memoryInfo.reset(new MockMemoryInfo());
873     executionEnvironment.rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr<DriverModel>(drm));
874     TestedDrmMemoryManager memoryManager(executionEnvironment);
875 
876     auto memoryInfo = drm->getMemoryInfo();
877     ASSERT_NE(nullptr, memoryInfo);
878     EXPECT_EQ(0u, memoryManager.getLocalMemorySize(0u, 0u));
879 }
880 
TEST_F(DrmMemoryManagerTestImpl,givenDrmMemoryManagerWhenGetLocalMemorySizeIsCalledButMemoryInfoIsNotAvailableThenSizeZeroIsReturned)881 TEST_F(DrmMemoryManagerTestImpl, givenDrmMemoryManagerWhenGetLocalMemorySizeIsCalledButMemoryInfoIsNotAvailableThenSizeZeroIsReturned) {
882     MockExecutionEnvironment executionEnvironment;
883     executionEnvironment.rootDeviceEnvironments[0]->osInterface = std::make_unique<OSInterface>();
884     auto drm = new DrmMock(*executionEnvironment.rootDeviceEnvironments[0]);
885     executionEnvironment.rootDeviceEnvironments[0]->osInterface->setDriverModel(std::unique_ptr<DriverModel>(drm));
886     TestedDrmMemoryManager memoryManager(executionEnvironment);
887 
888     EXPECT_EQ(0u, memoryManager.getLocalMemorySize(0u, 0xF));
889 }
890 
HWTEST2_F(DrmMemoryManagerLocalMemoryTest,givenGraphicsAllocationInDevicePoolIsAllocatedForImage1DWhenTheSizeReturnedFromGmmIsUnalignedThenCreateBufferObjectWithSizeAlignedTo64KB,NonDefaultIoctlsSupported)891 HWTEST2_F(DrmMemoryManagerLocalMemoryTest, givenGraphicsAllocationInDevicePoolIsAllocatedForImage1DWhenTheSizeReturnedFromGmmIsUnalignedThenCreateBufferObjectWithSizeAlignedTo64KB, NonDefaultIoctlsSupported) {
892     ImageDescriptor imgDesc = {};
893     imgDesc.imageType = ImageType::Image1D;
894     imgDesc.imageWidth = 100;
895     auto imgInfo = MockGmm::initImgInfo(imgDesc, 0, nullptr);
896 
897     MemoryManager::AllocationStatus status = MemoryManager::AllocationStatus::Success;
898     AllocationData allocData;
899     allocData.allFlags = 0;
900     allocData.size = MemoryConstants::pageSize;
901     allocData.type = GraphicsAllocation::AllocationType::IMAGE;
902     allocData.flags.resource48Bit = true;
903     allocData.imgInfo = &imgInfo;
904     allocData.rootDeviceIndex = rootDeviceIndex;
905 
906     auto allocation = memoryManager->allocateGraphicsMemoryInDevicePool(allocData, status);
907     EXPECT_NE(nullptr, allocation);
908     EXPECT_EQ(MemoryManager::AllocationStatus::Success, status);
909 
910     EXPECT_TRUE(allocData.imgInfo->useLocalMemory);
911     EXPECT_EQ(MemoryPool::LocalMemory, allocation->getMemoryPool());
912 
913     auto gmm = allocation->getDefaultGmm();
914     EXPECT_NE(nullptr, gmm);
915     EXPECT_FALSE(gmm->useSystemMemoryPool);
916 
917     auto gpuAddress = allocation->getGpuAddress();
918     auto sizeAlignedTo64KB = alignUp(allocData.imgInfo->size, MemoryConstants::pageSize64k);
919     EXPECT_NE(0u, gpuAddress);
920     EXPECT_EQ(sizeAlignedTo64KB, allocation->getUnderlyingBufferSize());
921     EXPECT_EQ(gpuAddress, reinterpret_cast<uint64_t>(allocation->getReservedAddressPtr()));
922     EXPECT_EQ(sizeAlignedTo64KB, allocation->getReservedAddressSize());
923 
924     auto drmAllocation = static_cast<DrmAllocation *>(allocation);
925     auto bo = drmAllocation->getBO();
926     EXPECT_NE(nullptr, bo);
927     EXPECT_EQ(gpuAddress, bo->peekAddress());
928     EXPECT_EQ(sizeAlignedTo64KB, bo->peekSize());
929 
930     memoryManager->freeGraphicsMemory(allocation);
931 }
932 
933 static uint32_t munmapCalledCount = 0u;
934 
HWTEST2_F(DrmMemoryManagerLocalMemoryTest,givenAlignmentAndSizeWhenMmapReturnsUnalignedPointerThenCreateAllocWithAlignmentUnmapTwoUnalignedPart,NonDefaultIoctlsSupported)935 HWTEST2_F(DrmMemoryManagerLocalMemoryTest, givenAlignmentAndSizeWhenMmapReturnsUnalignedPointerThenCreateAllocWithAlignmentUnmapTwoUnalignedPart, NonDefaultIoctlsSupported) {
936     DebugManagerStateRestore restorer;
937     DebugManager.flags.EnableBOMmapCreate.set(-1);
938 
939     MemoryRegion regionInfo[2] = {};
940     regionInfo[0].region = {I915_MEMORY_CLASS_SYSTEM, 0};
941     regionInfo[1].region = {I915_MEMORY_CLASS_DEVICE, 0};
942 
943     mock->memoryInfo.reset(new MemoryInfo(regionInfo, 2));
944     mock->ioctlCallsCount = 0;
945 
946     AllocationData allocationData;
947     allocationData.size = MemoryConstants::pageSize64k;
948 
949     memoryManager->mmapFunction = [](void *addr, size_t len, int prot,
950                                      int flags, int fd, off_t offset) throw() {
951         if (addr == 0) {
952             return reinterpret_cast<void *>(0x12345678);
953         } else {
954             return addr;
955         }
956     };
957 
958     memoryManager->munmapFunction = [](void *addr, size_t len) throw() {
959         munmapCalledCount++;
960         return 0;
961     };
962 
963     munmapCalledCount = 0;
964     auto allocation = memoryManager->createAllocWithAlignment(allocationData, MemoryConstants::pageSize, MemoryConstants::pageSize64k, MemoryConstants::pageSize64k, 0u);
965 
966     EXPECT_EQ(alignUp(reinterpret_cast<void *>(0x12345678), MemoryConstants::pageSize64k), allocation->getMmapPtr());
967     EXPECT_EQ(munmapCalledCount, 2u);
968     munmapCalledCount = 0u;
969     memoryManager->freeGraphicsMemory(allocation);
970 }
971 
HWTEST2_F(DrmMemoryManagerLocalMemoryTest,givenAlignmentAndSizeWhenMmapReturnsAlignedThenCreateAllocWithAlignmentUnmapOneUnalignedPart,NonDefaultIoctlsSupported)972 HWTEST2_F(DrmMemoryManagerLocalMemoryTest, givenAlignmentAndSizeWhenMmapReturnsAlignedThenCreateAllocWithAlignmentUnmapOneUnalignedPart, NonDefaultIoctlsSupported) {
973     DebugManagerStateRestore restorer;
974     DebugManager.flags.EnableBOMmapCreate.set(-1);
975 
976     MemoryRegion regionInfo[2] = {};
977     regionInfo[0].region = {I915_MEMORY_CLASS_SYSTEM, 0};
978     regionInfo[1].region = {I915_MEMORY_CLASS_DEVICE, 0};
979 
980     mock->memoryInfo.reset(new MemoryInfo(regionInfo, 2));
981     mock->ioctlCallsCount = 0;
982 
983     AllocationData allocationData;
984     allocationData.size = MemoryConstants::pageSize64k;
985 
986     memoryManager->mmapFunction = [](void *addr, size_t len, int prot,
987                                      int flags, int fd, off_t offset) throw() {
988         if (addr == 0) {
989             return reinterpret_cast<void *>(0x12345678);
990         } else {
991             return addr;
992         }
993     };
994 
995     memoryManager->munmapFunction = [](void *addr, size_t len) throw() {
996         munmapCalledCount++;
997         return 0;
998     };
999 
1000     munmapCalledCount = 0u;
1001     auto allocation = memoryManager->createAllocWithAlignment(allocationData, MemoryConstants::pageSize, 1u, MemoryConstants::pageSize64k, 0u);
1002 
1003     EXPECT_EQ(reinterpret_cast<void *>(0x12345678), allocation->getMmapPtr());
1004     EXPECT_EQ(munmapCalledCount, 1u);
1005     munmapCalledCount = 0u;
1006     memoryManager->freeGraphicsMemory(allocation);
1007 }
1008 
TEST_F(DrmMemoryManagerLocalMemoryTest,givenAllocationWithInvalidCacheRegionWhenAllocatingInDevicePoolThenReturnNullptr)1009 TEST_F(DrmMemoryManagerLocalMemoryTest, givenAllocationWithInvalidCacheRegionWhenAllocatingInDevicePoolThenReturnNullptr) {
1010     MemoryManager::AllocationStatus status = MemoryManager::AllocationStatus::Success;
1011     AllocationData allocData;
1012     allocData.allFlags = 0;
1013     allocData.size = 18 * MemoryConstants::pageSize64k;
1014     allocData.flags.allocateMemory = true;
1015     allocData.type = GraphicsAllocation::AllocationType::BUFFER;
1016     allocData.storageInfo.memoryBanks = maxNBitValue(MemoryBanks::getBankForLocalMemory(3));
1017     allocData.storageInfo.multiStorage = true;
1018     allocData.rootDeviceIndex = rootDeviceIndex;
1019     allocData.cacheRegion = 0xFFFF;
1020 
1021     auto allocation = memoryManager->allocateGraphicsMemoryInDevicePool(allocData, status);
1022     ASSERT_EQ(nullptr, allocation);
1023     EXPECT_EQ(MemoryManager::AllocationStatus::Error, status);
1024     memoryManager->freeGraphicsMemory(allocation);
1025 }
1026 
TEST_F(DrmMemoryManagerLocalMemoryTest,givenAllocationWithUnifiedMemoryAllocationThenReturnNullptr)1027 TEST_F(DrmMemoryManagerLocalMemoryTest, givenAllocationWithUnifiedMemoryAllocationThenReturnNullptr) {
1028     MemoryManager::AllocationStatus status = MemoryManager::AllocationStatus::Success;
1029     AllocationData allocData;
1030     allocData.allFlags = 0;
1031     allocData.size = 18 * MemoryConstants::pageSize64k;
1032     allocData.flags.allocateMemory = true;
1033     allocData.type = GraphicsAllocation::AllocationType::UNIFIED_SHARED_MEMORY;
1034     allocData.rootDeviceIndex = rootDeviceIndex;
1035 
1036     auto allocation = memoryManager->allocateGraphicsMemoryInDevicePool(allocData, status);
1037     ASSERT_EQ(nullptr, allocation);
1038     EXPECT_EQ(MemoryManager::AllocationStatus::Error, status);
1039     memoryManager->freeGraphicsMemory(allocation);
1040 }
1041 
TEST(ResidencyTests,whenBuffersIsCreatedWithMakeResidentFlagThenItSuccessfulyCreates)1042 TEST(ResidencyTests, whenBuffersIsCreatedWithMakeResidentFlagThenItSuccessfulyCreates) {
1043     VariableBackup<UltHwConfig> backup(&ultHwConfig);
1044     ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false;
1045     ultHwConfig.forceOsAgnosticMemoryManager = false;
1046     DebugManagerStateRestore restorer;
1047     DebugManager.flags.MakeAllBuffersResident.set(true);
1048 
1049     initPlatform();
1050     auto device = platform()->getClDevice(0u);
1051 
1052     MockContext context(device, false);
1053     auto retValue = CL_SUCCESS;
1054     auto clBuffer = clCreateBuffer(&context, 0u, 4096u, nullptr, &retValue);
1055     ASSERT_EQ(retValue, CL_SUCCESS);
1056     clReleaseMemObject(clBuffer);
1057 }
1058 
1059 } // namespace NEO
1060