From edf066a54bbb86428a7dbba5c6e282d7646ecc1b Mon Sep 17 00:00:00 2001 From: Kamil Diedrich Date: Wed, 17 Feb 2021 22:17:01 +0100 Subject: [PATCH] Return proper clDevice for given media adapter Signed-off-by: Kamil Diedrich --- opencl/source/sharings/va/CMakeLists.txt | 3 +- opencl/source/sharings/va/cl_va_api.cpp | 7 +- opencl/source/sharings/va/va_device.cpp | 4 +- opencl/source/sharings/va/va_device.h | 3 +- .../source/sharings/va/va_device_shared.cpp | 67 ++++++ .../linux/sys_calls_linux_ult.cpp | 39 +++- .../unit_test/sharings/va/va_device_tests.cpp | 21 +- .../sharings/va/va_sharing_tests.cpp | 192 ++++++++++++++++-- shared/source/os_interface/linux/sys_calls.h | 7 +- .../os_interface/linux/sys_calls_linux.cpp | 26 ++- 10 files changed, 328 insertions(+), 41 deletions(-) create mode 100644 opencl/source/sharings/va/va_device_shared.cpp diff --git a/opencl/source/sharings/va/CMakeLists.txt b/opencl/source/sharings/va/CMakeLists.txt index 06d3a12e32..9206bf857e 100644 --- a/opencl/source/sharings/va/CMakeLists.txt +++ b/opencl/source/sharings/va/CMakeLists.txt @@ -1,5 +1,5 @@ # -# Copyright (C) 2017-2020 Intel Corporation +# Copyright (C) 2017-2021 Intel Corporation # # SPDX-License-Identifier: MIT # @@ -8,6 +8,7 @@ set(RUNTIME_SRCS_SHARINGS_VA ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ${CMAKE_CURRENT_SOURCE_DIR}/${BRANCH_DIR_SUFFIX}/va_device.cpp ${CMAKE_CURRENT_SOURCE_DIR}/va_device.h + ${CMAKE_CURRENT_SOURCE_DIR}/va_device_shared.cpp ${CMAKE_CURRENT_SOURCE_DIR}/${BRANCH_DIR_SUFFIX}/va_extension.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cl_va_api.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cl_va_api.h diff --git a/opencl/source/sharings/va/cl_va_api.cpp b/opencl/source/sharings/va/cl_va_api.cpp index d2b78eae11..e4c2afe389 100644 --- a/opencl/source/sharings/va/cl_va_api.cpp +++ b/opencl/source/sharings/va/cl_va_api.cpp @@ -75,7 +75,12 @@ clGetDeviceIDsFromVA_APIMediaAdapterINTEL(cl_platform_id platform, cl_va_api_dev VADevice vaDevice{}; cl_device_id device = vaDevice.getDeviceFromVA(pPlatform, mediaAdapter); GetInfoHelper::set(devices, device); - GetInfoHelper::set(numDevices, 1u); + if (device == nullptr) { + GetInfoHelper::set(numDevices, 0u); + status = CL_DEVICE_NOT_FOUND; + } else { + GetInfoHelper::set(numDevices, 1u); + } } return status; } diff --git a/opencl/source/sharings/va/va_device.cpp b/opencl/source/sharings/va/va_device.cpp index a88acf88d2..3bfe206e25 100644 --- a/opencl/source/sharings/va/va_device.cpp +++ b/opencl/source/sharings/va/va_device.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -16,7 +16,7 @@ VADevice::VADevice() { } ClDevice *VADevice::getDeviceFromVA(Platform *pPlatform, VADisplay vaDisplay) { - return pPlatform->getClDevice(0); + return getRootDeviceFromVaDisplay(pPlatform, vaDisplay); } VADevice::~VADevice() { diff --git a/opencl/source/sharings/va/va_device.h b/opencl/source/sharings/va/va_device.h index 7e978a1cb4..c301732d95 100644 --- a/opencl/source/sharings/va/va_device.h +++ b/opencl/source/sharings/va/va_device.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -20,6 +20,7 @@ class VADevice { VADevice(); virtual ~VADevice(); + ClDevice *getRootDeviceFromVaDisplay(Platform *pPlatform, VADisplay vaDisplay); ClDevice *getDeviceFromVA(Platform *pPlatform, VADisplay vaDisplay); static std::function fdlopen; diff --git a/opencl/source/sharings/va/va_device_shared.cpp b/opencl/source/sharings/va/va_device_shared.cpp new file mode 100644 index 0000000000..a2afc30cf7 --- /dev/null +++ b/opencl/source/sharings/va/va_device_shared.cpp @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2021 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "shared/source/device/device.h" +#include "shared/source/os_interface/linux/drm_neo.h" +#include "shared/source/os_interface/linux/os_interface.h" +#include "shared/source/os_interface/linux/sys_calls.h" + +#include "opencl/source/cl_device/cl_device.h" +#include "opencl/source/platform/platform.h" +#include "opencl/source/sharings/va/va_device.h" + +#include +#include +#include +#include + +namespace NEO { +ClDevice *VADevice::getRootDeviceFromVaDisplay(Platform *pPlatform, VADisplay vaDisplay) { + VADisplayContextP pDisplayContext_test = reinterpret_cast(vaDisplay); + UNRECOVERABLE_IF(pDisplayContext_test->vadpy_magic != 0x56414430); + VADriverContextP pDriverContext_test = pDisplayContext_test->pDriverContext; + int deviceFd = *(int *)pDriverContext_test->drm_state; + + UNRECOVERABLE_IF(deviceFd < 0); + + char path[256] = {0}; + size_t pathlen = 256; + + if (SysCalls::getDevicePath(deviceFd, path, pathlen)) { + return nullptr; + } + + if (SysCalls::access(path, F_OK)) { + return nullptr; + } + + int readLinkSize = 0; + char devicePath[256] = {0}; + readLinkSize = SysCalls::readlink(path, devicePath, pathlen); + + if (readLinkSize == -1) { + return nullptr; + } + + std::string_view prefixView = "../../devices/pci0000:00/0000:"; + std::string_view devicePathView(devicePath, static_cast(readLinkSize)); + devicePathView.remove_prefix(prefixView.size()); + devicePathView = devicePathView.substr(0, 7); + + for (size_t i = 0; i < pPlatform->getNumDevices(); ++i) { + auto device = pPlatform->getClDevice(i); + NEO::Device *neoDevice = &device->getDevice(); + + auto *drm = neoDevice->getRootDeviceEnvironment().osInterface->get()->getDrm(); + auto pciPath = drm->getPciPath(); + if (devicePathView == pciPath) { + return device; + } + } + return nullptr; +} +} // namespace NEO diff --git a/opencl/test/unit_test/os_interface/linux/sys_calls_linux_ult.cpp b/opencl/test/unit_test/os_interface/linux/sys_calls_linux_ult.cpp index a6d8e8a9e6..9791099f91 100644 --- a/opencl/test/unit_test/os_interface/linux/sys_calls_linux_ult.cpp +++ b/opencl/test/unit_test/os_interface/linux/sys_calls_linux_ult.cpp @@ -1,10 +1,11 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * */ +#include "shared/source/helpers/string.h" #include "shared/source/os_interface/linux/sys_calls.h" #include "drm/i915_drm.h" @@ -12,7 +13,11 @@ #include #include #include +#include +#include +#include #include +#include namespace NEO { namespace SysCalls { @@ -20,6 +25,8 @@ uint32_t closeFuncCalled = 0u; int closeFuncArgPassed = 0; constexpr int fakeFileDescriptor = 123; uint32_t vmId = 0; +bool makeFakeDevicePath = false; +bool allowFakeDevicePath = false; int close(int fileDescriptor) { closeFuncCalled++; @@ -55,5 +62,35 @@ int ioctl(int fileDescriptor, unsigned long int request, void *arg) { } return 0; } + +int access(const char *pathName, int mode) { + if (allowFakeDevicePath || strcmp(pathName, "/sys/dev/char/226:128") == 0) { + return 0; + } + return -1; +} + +int readlink(const char *path, char *buf, size_t bufsize) { + if (strcmp(path, "/sys/dev/char/226:128") != 0) { + return -1; + } + + constexpr size_t sizeofPath = sizeof("../../devices/pci0000:00/0000:00:02.0/drm/renderD128"); + + strcpy_s(buf, sizeofPath, "../../devices/pci0000:00/0000:00:02.0/drm/renderD128"); + return sizeofPath; +} + +int getDevicePath(int deviceFd, char *buf, size_t &bufSize) { + if (deviceFd <= 0) { + return -1; + } + constexpr size_t sizeofPath = sizeof("/sys/dev/char/226:128"); + + makeFakeDevicePath ? strcpy_s(buf, sizeofPath, "/sys/dev/char/xyzwerq") : strcpy_s(buf, sizeofPath, "/sys/dev/char/226:128"); + bufSize = sizeofPath; + + return 0; +} } // namespace SysCalls } // namespace NEO diff --git a/opencl/test/unit_test/sharings/va/va_device_tests.cpp b/opencl/test/unit_test/sharings/va/va_device_tests.cpp index 8798fcbbb7..f1b5debea9 100644 --- a/opencl/test/unit_test/sharings/va/va_device_tests.cpp +++ b/opencl/test/unit_test/sharings/va/va_device_tests.cpp @@ -1,25 +1,6 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * */ - -#include "opencl/source/cl_device/cl_device.h" -#include "opencl/source/platform/platform.h" -#include "opencl/source/sharings/va/va_device.h" -#include "opencl/test/unit_test/fixtures/platform_fixture.h" -#include "test.h" - -using namespace NEO; - -using VaDeviceTests = Test; - -TEST_F(VaDeviceTests, givenVADeviceWhenGetDeviceFromVAIsCalledThenRootDeviceIsReturned) { - VADisplay vaDisplay = nullptr; - - VADevice vaDevice{}; - ClDevice *device = vaDevice.getDeviceFromVA(pPlatform, vaDisplay); - - EXPECT_EQ(pPlatform->getClDevice(0), device); -} diff --git a/opencl/test/unit_test/sharings/va/va_sharing_tests.cpp b/opencl/test/unit_test/sharings/va/va_sharing_tests.cpp index 76b1654bc7..22f9fe9c11 100644 --- a/opencl/test/unit_test/sharings/va/va_sharing_tests.cpp +++ b/opencl/test/unit_test/sharings/va/va_sharing_tests.cpp @@ -5,15 +5,21 @@ * */ +#include "shared/source/device/device.h" #include "shared/source/gmm_helper/gmm.h" #include "shared/source/helpers/array_count.h" #include "shared/source/memory_manager/graphics_allocation.h" +#include "shared/source/os_interface/linux/drm_neo.h" +#include "shared/source/os_interface/linux/os_interface.h" #include "shared/test/common/helpers/debug_manager_state_restore.h" +#include "shared/test/common/helpers/ult_hw_config.h" +#include "shared/test/common/helpers/variable_backup.h" #include "opencl/source/api/api.h" #include "opencl/source/cl_device/cl_device.h" #include "opencl/source/platform/platform.h" #include "opencl/source/sharings/va/cl_va_api.h" +#include "opencl/source/sharings/va/va_device.h" #include "opencl/source/sharings/va/va_sharing.h" #include "opencl/source/sharings/va/va_surface.h" #include "opencl/test/unit_test/fixtures/platform_fixture.h" @@ -22,10 +28,14 @@ #include "opencl/test/unit_test/mocks/mock_command_queue.h" #include "opencl/test/unit_test/mocks/mock_context.h" #include "opencl/test/unit_test/mocks/mock_platform.h" +#include "opencl/test/unit_test/os_interface/linux/drm_mock.h" #include "opencl/test/unit_test/sharings/va/mock_va_sharing.h" +#include "test.h" #include "gtest/gtest.h" +#include + using namespace NEO; class VaSharingTests : public ::testing::Test, public PlatformFixture { @@ -556,19 +566,6 @@ TEST_F(VaSharingTests, givenContextWhenSharingTableEmptyThenReturnsNullptr) { EXPECT_EQ(sharingF, nullptr); } -TEST_F(VaSharingTests, givenValidPlatformWhenGetDeviceIdsFromVaApiMediaAdapterCalledThenReturnFirstDevice) { - cl_device_id devices = 0; - cl_uint numDevices = 0; - - cl_platform_id platformId = this->pPlatform; - - auto errCode = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platformId, 0u, nullptr, 0u, 1, &devices, &numDevices); - EXPECT_EQ(CL_SUCCESS, errCode); - EXPECT_EQ(1u, numDevices); - EXPECT_NE(nullptr, platform()->getClDevice(0)); - EXPECT_EQ(platform()->getClDevice(0), devices); -} - TEST_F(VaSharingTests, givenInValidPlatformWhenGetDeviceIdsFromVaApiMediaAdapterCalledThenReturnFirstDevice) { cl_device_id devices = 0; cl_uint numDevices = 0; @@ -1227,3 +1224,172 @@ TEST_F(VaSharingTests, givenPlaneArgumentEquals2WithoutNoProperFormatsThenReturn EXPECT_EQ(result, CL_SUCCESS); } + +class VaDeviceTests : public Test { + public: + VaDeviceTests() { + ultHwConfig.useMockedPrepareDeviceEnvironmentsFunc = false; + } + VariableBackup backup{&ultHwConfig}; +}; + +TEST_F(VaDeviceTests, givenVADeviceWhenGetDeviceFromVAIsCalledThenRootDeviceIsReturned) { + auto vaDisplay = std::make_unique(); + vaDisplay->vadpy_magic = 0x56414430; + auto contextPtr = std::make_unique(); + auto drmState = std::make_unique(); + vaDisplay->pDriverContext = contextPtr.get(); + contextPtr->drm_state = drmState.get(); + *(int *)contextPtr->drm_state = 1; + + auto device = pPlatform->getClDevice(0); + NEO::Device *neoDevice = &device->getDevice(); + + auto mockDrm = static_cast(neoDevice->getRootDeviceEnvironment().osInterface->get()->getDrm()); + mockDrm->setPciPath("00:02.0"); + + VADevice vaDevice{}; + auto clDevice = vaDevice.getDeviceFromVA(pPlatform, vaDisplay.get()); + EXPECT_NE(clDevice, nullptr); +} + +TEST_F(VaDeviceTests, givenVADeviceAndInvalidPciPathOfClDeviceWhenGetDeviceFromVAIsCalledThenNullptrIsReturned) { + auto vaDisplay = std::make_unique(); + vaDisplay->vadpy_magic = 0x56414430; + auto contextPtr = std::make_unique(); + auto drmState = std::make_unique(); + vaDisplay->pDriverContext = contextPtr.get(); + contextPtr->drm_state = drmState.get(); + *(int *)contextPtr->drm_state = 1; + + auto device = pPlatform->getClDevice(0); + NEO::Device *neoDevice = &device->getDevice(); + + auto mockDrm = static_cast(neoDevice->getRootDeviceEnvironment().osInterface->get()->getDrm()); + mockDrm->setPciPath("00:00.0"); + + VADevice vaDevice{}; + auto clDevice = vaDevice.getDeviceFromVA(pPlatform, vaDisplay.get()); + EXPECT_EQ(clDevice, nullptr); +} + +TEST_F(VaDeviceTests, givenVADeviceAndInvalidFDWhenGetDeviceFromVAIsCalledThenNullptrIsReturned) { + auto vaDisplay = std::make_unique(); + vaDisplay->vadpy_magic = 0x56414430; + auto contextPtr = std::make_unique(); + auto drmState = std::make_unique(); + vaDisplay->pDriverContext = contextPtr.get(); + contextPtr->drm_state = drmState.get(); + *(int *)contextPtr->drm_state = 0; + + VADevice vaDevice{}; + auto clDevice = vaDevice.getDeviceFromVA(pPlatform, vaDisplay.get()); + EXPECT_EQ(clDevice, nullptr); +} + +TEST_F(VaDeviceTests, givenVADeviceAndInvalidMagicNumberWhenGetDeviceFromVAIsCalledThenUnrecoverableIsCalled) { + auto vaDisplay = std::make_unique(); + vaDisplay->vadpy_magic = 0x0; + + VADevice vaDevice{}; + EXPECT_ANY_THROW(vaDevice.getDeviceFromVA(pPlatform, vaDisplay.get())); +} + +TEST_F(VaDeviceTests, givenVADeviceAndNegativeFdWhenGetDeviceFromVAIsCalledThenUnrecoverableIsCalled) { + auto vaDisplay = std::make_unique(); + vaDisplay->vadpy_magic = 0x56414430; + auto contextPtr = std::make_unique(); + auto drmState = std::make_unique(); + vaDisplay->pDriverContext = contextPtr.get(); + contextPtr->drm_state = drmState.get(); + *(int *)contextPtr->drm_state = -1; + + VADevice vaDevice{}; + EXPECT_ANY_THROW(vaDevice.getDeviceFromVA(pPlatform, vaDisplay.get())); +} + +namespace NEO { +namespace SysCalls { +extern bool makeFakeDevicePath; +extern bool allowFakeDevicePath; +} // namespace SysCalls +} // namespace NEO + +TEST_F(VaDeviceTests, givenVADeviceAndFakeDevicePathWhenGetDeviceFromVAIsCalledThenNullptrIsReturned) { + VariableBackup makeFakePathBackup(&SysCalls::makeFakeDevicePath, true); + auto vaDisplay = std::make_unique(); + vaDisplay->vadpy_magic = 0x56414430; + auto contextPtr = std::make_unique(); + auto drmState = std::make_unique(); + vaDisplay->pDriverContext = contextPtr.get(); + contextPtr->drm_state = drmState.get(); + *(int *)contextPtr->drm_state = 1; + + VADevice vaDevice{}; + auto clDevice = vaDevice.getDeviceFromVA(pPlatform, vaDisplay.get()); + EXPECT_EQ(clDevice, nullptr); +} + +TEST_F(VaDeviceTests, givenVADeviceAndAbsolutePathWhenGetDeviceFromVAIsCalledThenNullptrIsReturned) { + VariableBackup makeFakePathBackup(&SysCalls::makeFakeDevicePath, true); + VariableBackup allowFakeDevicePathBackup(&SysCalls::allowFakeDevicePath, true); + auto vaDisplay = std::make_unique(); + vaDisplay->vadpy_magic = 0x56414430; + auto contextPtr = std::make_unique(); + auto drmState = std::make_unique(); + vaDisplay->pDriverContext = contextPtr.get(); + contextPtr->drm_state = drmState.get(); + *(int *)contextPtr->drm_state = 1; + + VADevice vaDevice{}; + auto clDevice = vaDevice.getDeviceFromVA(pPlatform, vaDisplay.get()); + EXPECT_EQ(clDevice, nullptr); +} + +TEST_F(VaDeviceTests, givenValidPlatformWithInvalidVaDisplayWhenGetDeviceIdsFromVaApiMediaAdapterCalledThenReturnNullptrAndZeroDevices) { + cl_device_id devices = 0; + cl_uint numDevices = 0; + cl_platform_id platformId = pPlatform; + auto vaDisplay = std::make_unique(); + vaDisplay->vadpy_magic = 0x56414430; + auto contextPtr = std::make_unique(); + auto drmState = std::make_unique(); + vaDisplay->pDriverContext = contextPtr.get(); + contextPtr->drm_state = drmState.get(); + *(int *)contextPtr->drm_state = 1; + + auto device = pPlatform->getClDevice(0); + NEO::Device *neoDevice = &device->getDevice(); + + auto mockDrm = static_cast(neoDevice->getRootDeviceEnvironment().osInterface->get()->getDrm()); + mockDrm->setPciPath("00:00.0"); + + auto errCode = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platformId, 0u, vaDisplay.get(), 0u, 1, &devices, &numDevices); + EXPECT_EQ(CL_DEVICE_NOT_FOUND, errCode); + EXPECT_EQ(0u, numDevices); + EXPECT_EQ(nullptr, devices); +} + +TEST_F(VaDeviceTests, givenValidPlatformWhenGetDeviceIdsFromVaApiMediaAdapterCalledThenReturnFirstDevice) { + cl_device_id devices = 0; + cl_uint numDevices = 0; + cl_platform_id platformId = pPlatform; + auto vaDisplay = std::make_unique(); + vaDisplay->vadpy_magic = 0x56414430; + auto contextPtr = std::make_unique(); + auto drmState = std::make_unique(); + vaDisplay->pDriverContext = contextPtr.get(); + contextPtr->drm_state = drmState.get(); + *(int *)contextPtr->drm_state = 1; + + auto device = pPlatform->getClDevice(0); + NEO::Device *neoDevice = &device->getDevice(); + + auto mockDrm = static_cast(neoDevice->getRootDeviceEnvironment().osInterface->get()->getDrm()); + mockDrm->setPciPath("00:02.0"); + + auto errCode = clGetDeviceIDsFromVA_APIMediaAdapterINTEL(platformId, 0u, vaDisplay.get(), 0u, 1, &devices, &numDevices); + EXPECT_EQ(CL_SUCCESS, errCode); + EXPECT_EQ(1u, numDevices); + EXPECT_EQ(pPlatform->getClDevice(0), devices); +} diff --git a/shared/source/os_interface/linux/sys_calls.h b/shared/source/os_interface/linux/sys_calls.h index db5e021809..9deb6d7337 100644 --- a/shared/source/os_interface/linux/sys_calls.h +++ b/shared/source/os_interface/linux/sys_calls.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -7,10 +7,15 @@ #pragma once +#include + namespace NEO { namespace SysCalls { int close(int fileDescriptor); int open(const char *file, int flags); int ioctl(int fileDescriptor, unsigned long int request, void *arg); +int getDevicePath(int deviceFd, char *buf, size_t &bufSize); +int access(const char *pathname, int mode); +int readlink(const char *path, char *buf, size_t bufsize); } // namespace SysCalls } // namespace NEO diff --git a/shared/source/os_interface/linux/sys_calls_linux.cpp b/shared/source/os_interface/linux/sys_calls_linux.cpp index 61e8f5092f..57fa17c6e1 100644 --- a/shared/source/os_interface/linux/sys_calls_linux.cpp +++ b/shared/source/os_interface/linux/sys_calls_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020-2021 Intel Corporation * * SPDX-License-Identifier: MIT * @@ -8,7 +8,11 @@ #include "shared/source/os_interface/linux/sys_calls.h" #include +#include +#include #include +#include +#include #include namespace NEO { @@ -22,5 +26,25 @@ int open(const char *file, int flags) { int ioctl(int fileDescriptor, unsigned long int request, void *arg) { return ::ioctl(fileDescriptor, request, arg); } + +int access(const char *pathName, int mode) { + return ::access(pathName, mode); +} + +int readlink(const char *path, char *buf, size_t bufsize) { + return static_cast(::readlink(path, buf, bufsize)); +} + +int getDevicePath(int deviceFd, char *buf, size_t &bufSize) { + struct stat st; + if (fstat(deviceFd, &st)) { + return -1; + } + + snprintf(buf, bufSize, "/sys/dev/char/%d:%d", + major(st.st_rdev), minor(st.st_rdev)); + + return 0; +} } // namespace SysCalls } // namespace NEO