/* * Copyright (c) 2017 - 2018, Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ #pragma once #include "drm/i915_drm.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "runtime/helpers/aligned_memory.h" #include "runtime/os_interface/linux/drm_memory_manager.h" #include "runtime/os_interface/linux/drm_neo.h" #include "unit_tests/helpers/gtest_helpers.h" #include #include #define RENDER_DEVICE_NAME_MATCHER ::testing::StrEq("/dev/dri/renderD128") using OCLRT::Drm; static const int mockFd = 33; class DrmMockImpl : public Drm { public: DrmMockImpl(int fd) : Drm(fd){}; MOCK_METHOD2(ioctl, int(unsigned long request, void *arg)); }; class DrmMockSuccess : public Drm { public: DrmMockSuccess() : Drm(mockFd) {} int ioctl(unsigned long request, void *arg) override { return 0; }; }; class DrmMockFail : public Drm { public: DrmMockFail() : Drm(mockFd) {} int ioctl(unsigned long request, void *arg) override { return -1; }; }; class DrmMockTime : public DrmMockSuccess { public: int ioctl(unsigned long request, void *arg) override { drm_i915_reg_read *reg = reinterpret_cast(arg); reg->val = getVal() << 32; return 0; }; uint64_t getVal() { static uint64_t val = 0; return ++val; } }; class DrmMockCustom : public Drm { public: struct IoctlResExt { int32_t no; int32_t res; IoctlResExt(int32_t no, int32_t res) : no(no), res(res) {} }; void overideCoherencyPatchActive(bool newCoherencyPatchActiveValue) { coherencyDisablePatchActive = newCoherencyPatchActiveValue; } void overideDataPortCoherencyPatchActive(bool newValue) { dataPortCoherencyPatchActive = newValue; } class Ioctls { public: void reset() { total = 0; execbuffer2 = 0; gemUserptr = 0; gemCreate = 0; gemSetTiling = 0; primeFdToHandle = 0; gemMmap = 0; gemSetDomain = 0; gemWait = 0; gemClose = 0; regRead = 0; contextGetParam = 0; } std::atomic total; std::atomic execbuffer2; std::atomic gemUserptr; std::atomic gemCreate; std::atomic gemSetTiling; std::atomic primeFdToHandle; std::atomic gemMmap; std::atomic gemSetDomain; std::atomic gemWait; std::atomic gemClose; std::atomic regRead; std::atomic contextGetParam; }; std::atomic ioctl_res; Ioctls ioctl_cnt; Ioctls ioctl_expected; std::atomic ioctl_res_ext; void testIoctls() { if (this->ioctl_expected.total == -1) return; #define NEO_IOCTL_EXPECT_EQ(PARAM) \ if (this->ioctl_expected.PARAM >= 0) { \ EXPECT_EQ(this->ioctl_expected.PARAM, this->ioctl_cnt.PARAM); \ } NEO_IOCTL_EXPECT_EQ(execbuffer2); NEO_IOCTL_EXPECT_EQ(gemUserptr); NEO_IOCTL_EXPECT_EQ(gemCreate); NEO_IOCTL_EXPECT_EQ(gemSetTiling); NEO_IOCTL_EXPECT_EQ(primeFdToHandle); NEO_IOCTL_EXPECT_EQ(gemMmap); NEO_IOCTL_EXPECT_EQ(gemSetDomain); NEO_IOCTL_EXPECT_EQ(gemWait); NEO_IOCTL_EXPECT_EQ(gemClose); NEO_IOCTL_EXPECT_EQ(regRead); NEO_IOCTL_EXPECT_EQ(contextGetParam); #undef NEO_IOCTL_EXPECT_EQ } //DRM_IOCTL_I915_GEM_EXECBUFFER2 drm_i915_gem_execbuffer2 execBuffer = {0}; //DRM_IOCTL_I915_GEM_CREATE __u64 createParamsSize = 0; __u32 createParamsHandle = 0; //DRM_IOCTL_I915_GEM_SET_TILING __u32 setTilingMode = 0; __u32 setTilingHandle = 0; __u32 setTilingStride = 0; //DRM_IOCTL_PRIME_FD_TO_HANDLE __u32 outputHandle = 0; __s32 inputFd = 0; //DRM_IOCTL_I915_GEM_USERPTR __u32 returnHandle = 0; //DRM_IOCTL_I915_GEM_MMAP __u32 mmapHandle = 0; __u32 mmapPad = 0; __u64 mmapOffset = 0; __u64 mmapSize = 0; __u64 mmapAddrPtr = 0x7F4000001000; __u64 mmapFlags = 0; //DRM_IOCTL_I915_GEM_SET_DOMAIN __u32 setDomainHandle = 0; __u32 setDomainReadDomains = 0; __u32 setDomainWriteDomain = 0; //DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM drm_i915_gem_context_param recordedGetContextParam = {0}; __u64 getContextParamRetValue = 0; int errnoValue = 0; int ioctl(unsigned long request, void *arg) override { auto ext = ioctl_res_ext.load(); //store flags switch (request) { case DRM_IOCTL_I915_GEM_EXECBUFFER2: { drm_i915_gem_execbuffer2 *execbuf = (drm_i915_gem_execbuffer2 *)arg; this->execBuffer = *execbuf; ioctl_cnt.execbuffer2++; } break; case DRM_IOCTL_I915_GEM_USERPTR: { auto *userPtrParams = (drm_i915_gem_userptr *)arg; userPtrParams->handle = returnHandle; returnHandle++; ioctl_cnt.gemUserptr++; } break; case DRM_IOCTL_I915_GEM_CREATE: { auto *createParams = (drm_i915_gem_create *)arg; this->createParamsSize = createParams->size; this->createParamsHandle = createParams->handle = 1u; ioctl_cnt.gemCreate++; } break; case DRM_IOCTL_I915_GEM_SET_TILING: { auto *setTilingParams = (drm_i915_gem_set_tiling *)arg; setTilingMode = setTilingParams->tiling_mode; setTilingHandle = setTilingParams->handle; setTilingStride = setTilingParams->stride; ioctl_cnt.gemSetTiling++; } break; case DRM_IOCTL_PRIME_FD_TO_HANDLE: { auto *primeToHandleParams = (drm_prime_handle *)arg; //return BO primeToHandleParams->handle = outputHandle; inputFd = primeToHandleParams->fd; ioctl_cnt.primeFdToHandle++; } break; case DRM_IOCTL_I915_GEM_MMAP: { auto mmapParams = (drm_i915_gem_mmap *)arg; mmapHandle = mmapParams->handle; mmapPad = mmapParams->pad; mmapOffset = mmapParams->offset; mmapSize = mmapParams->size; mmapFlags = mmapParams->flags; mmapParams->addr_ptr = mmapAddrPtr; ioctl_cnt.gemMmap++; } break; case DRM_IOCTL_I915_GEM_SET_DOMAIN: { auto setDomainParams = (drm_i915_gem_set_domain *)arg; setDomainHandle = setDomainParams->handle; setDomainReadDomains = setDomainParams->read_domains; setDomainWriteDomain = setDomainParams->write_domain; ioctl_cnt.gemSetDomain++; } break; case DRM_IOCTL_I915_GEM_WAIT: ioctl_cnt.gemWait++; break; case DRM_IOCTL_GEM_CLOSE: ioctl_cnt.gemClose++; break; case DRM_IOCTL_I915_REG_READ: ioctl_cnt.regRead++; break; case DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM: { ioctl_cnt.contextGetParam++; auto getContextParam = (drm_i915_gem_context_param *)arg; recordedGetContextParam = *getContextParam; getContextParam->value = getContextParamRetValue; } break; default: std::cout << std::hex << DRM_IOCTL_I915_GEM_WAIT << std::endl; std::cout << "unexpected IOCTL: " << std::hex << request << std::endl; UNRECOVERABLE_IF(true); } if (ext->no != -1 && ext->no == ioctl_cnt.total.load()) { ioctl_cnt.total.fetch_add(1); return ext->res; } ioctl_cnt.total.fetch_add(1); return ioctl_res.load(); }; IoctlResExt NONE = {-1, 0}; void reset() { ioctl_res = 0; ioctl_cnt.reset(); ioctl_expected.reset(); ioctl_res_ext = &NONE; } DrmMockCustom() : Drm(mockFd) { reset(); } int getErrno() override { return errnoValue; } };