/* * Copyright (C) 2022 Intel Corporation * * SPDX-License-Identifier: MIT * */ #include "shared/test/common/libult/linux/drm_mock_prelim_context.h" #include "shared/source/helpers/basic_math.h" #include "shared/source/helpers/ptr_math.h" #include "shared/source/os_interface/linux/cache_info_impl.h" #include "shared/test/common/libult/linux/drm_mock_helper.h" #include "third_party/uapi/prelim/drm/i915_drm.h" #include #include #include namespace { constexpr std::array copyEnginesCapsMap = {{ PRELIM_I915_COPY_CLASS_CAP_SATURATE_LMEM, PRELIM_I915_COPY_CLASS_CAP_SATURATE_PCIE, PRELIM_I915_COPY_CLASS_CAP_SATURATE_PCIE, PRELIM_I915_COPY_CLASS_CAP_SATURATE_LINK, PRELIM_I915_COPY_CLASS_CAP_SATURATE_LINK, PRELIM_I915_COPY_CLASS_CAP_SATURATE_LINK, PRELIM_I915_COPY_CLASS_CAP_SATURATE_LINK, PRELIM_I915_COPY_CLASS_CAP_SATURATE_LINK, PRELIM_I915_COPY_CLASS_CAP_SATURATE_LINK, }}; } // namespace int DrmMockPrelimContext::handlePrelimRequest(unsigned long request, void *arg) { switch (request) { case DRM_IOCTL_I915_GETPARAM: { auto gp = static_cast(arg); if (gp->param == PRELIM_I915_PARAM_HAS_PAGE_FAULT) { *gp->value = hasPageFaultQueryValue; return hasPageFaultQueryReturn; } else if (gp->param == PRELIM_I915_PARAM_HAS_VM_BIND) { vmBindQueryCalled++; *gp->value = vmBindQueryValue; return vmBindQueryReturn; } } break; case PRELIM_DRM_IOCTL_I915_GEM_CLOS_RESERVE: { auto closReserveArg = static_cast(arg); closIndex++; if (closIndex == 0) { return EINVAL; } closReserveArg->clos_index = closIndex; } break; case PRELIM_DRM_IOCTL_I915_GEM_CLOS_FREE: { auto closFreeArg = static_cast(arg); if (closFreeArg->clos_index > closIndex) { return EINVAL; } closIndex--; } break; case PRELIM_DRM_IOCTL_I915_GEM_CACHE_RESERVE: { auto cacheReserveArg = static_cast(arg); if (cacheReserveArg->clos_index > closIndex) { return EINVAL; } auto cacheInfoImpl = static_cast(cacheInfo); auto maxReservationNumWays = cacheInfoImpl ? cacheInfoImpl->getMaxReservationNumWays() : maxNumWays; if (cacheReserveArg->num_ways > maxReservationNumWays) { return EINVAL; } auto freeNumWays = maxReservationNumWays - allocNumWays; if (cacheReserveArg->num_ways > freeNumWays) { return EINVAL; } allocNumWays += cacheReserveArg->num_ways; } break; default: return -1; } return 0; } bool DrmMockPrelimContext::handlePrelimQueryItem(void *arg) { auto queryItem = reinterpret_cast(arg); auto >SystemInfo = hwInfo->gtSystemInfo; const auto numberOfCCS = gtSystemInfo.CCSInfo.IsValid && !disableCcsSupport ? gtSystemInfo.CCSInfo.NumberOfCCSEnabled : 0u; switch (queryItem->query_id) { case PRELIM_DRM_I915_QUERY_ENGINE_INFO: { auto numberOfTiles = gtSystemInfo.MultiTileArchInfo.IsValid ? gtSystemInfo.MultiTileArchInfo.TileCount : 1u; uint32_t numberOfEngines = numberOfTiles * (4u + numberOfCCS + static_cast(supportedCopyEnginesMask.count())); int engineInfoSize = sizeof(prelim_drm_i915_query_engine_info) + numberOfEngines * sizeof(prelim_drm_i915_engine_info); if (queryItem->length == 0) { queryItem->length = engineInfoSize; } else { EXPECT_EQ(engineInfoSize, queryItem->length); auto queryEngineInfo = reinterpret_cast(queryItem->data_ptr); EXPECT_EQ(0u, queryEngineInfo->num_engines); queryEngineInfo->num_engines = numberOfEngines; auto p = queryEngineInfo->engines; for (uint32_t tile = 0u; tile < numberOfTiles; tile++) { p++->engine = {I915_ENGINE_CLASS_RENDER, DrmMockHelper::getEngineOrMemoryInstanceValue(tile, 0)}; for (uint32_t i = 0u; i < supportedCopyEnginesMask.size(); i++) { if (supportedCopyEnginesMask.test(i)) { auto copyEngineInfo = p++; copyEngineInfo->engine = {I915_ENGINE_CLASS_COPY, DrmMockHelper::getEngineOrMemoryInstanceValue(tile, i)}; copyEngineInfo->capabilities = copyEnginesCapsMap[i]; } } p++->engine = {I915_ENGINE_CLASS_VIDEO, DrmMockHelper::getEngineOrMemoryInstanceValue(tile, 0)}; p++->engine = {I915_ENGINE_CLASS_VIDEO, DrmMockHelper::getEngineOrMemoryInstanceValue(tile, 0)}; p++->engine = {I915_ENGINE_CLASS_VIDEO_ENHANCE, DrmMockHelper::getEngineOrMemoryInstanceValue(tile, 0)}; for (auto i = 0u; i < numberOfCCS; i++) { p++->engine = {PRELIM_I915_ENGINE_CLASS_COMPUTE, DrmMockHelper::getEngineOrMemoryInstanceValue(tile, i)}; } } } break; } case PRELIM_DRM_I915_QUERY_MEMORY_REGIONS: { auto numberOfLocalMemories = gtSystemInfo.MultiTileArchInfo.IsValid ? gtSystemInfo.MultiTileArchInfo.TileCount : 0u; auto numberOfRegions = 1u + numberOfLocalMemories; int regionInfoSize = sizeof(prelim_drm_i915_query_memory_regions) + numberOfRegions * sizeof(prelim_drm_i915_memory_region_info); if (queryItem->length == 0) { queryItem->length = regionInfoSize; } else { EXPECT_EQ(regionInfoSize, queryItem->length); auto queryMemoryRegionInfo = reinterpret_cast(queryItem->data_ptr); EXPECT_EQ(0u, queryMemoryRegionInfo->num_regions); queryMemoryRegionInfo->num_regions = numberOfRegions; queryMemoryRegionInfo->regions[0].region.memory_class = PRELIM_I915_MEMORY_CLASS_SYSTEM; queryMemoryRegionInfo->regions[0].region.memory_instance = 1; queryMemoryRegionInfo->regions[0].probed_size = 2 * MemoryConstants::gigaByte; for (auto tile = 0u; tile < numberOfLocalMemories; tile++) { queryMemoryRegionInfo->regions[1 + tile].region.memory_class = PRELIM_I915_MEMORY_CLASS_DEVICE; queryMemoryRegionInfo->regions[1 + tile].region.memory_instance = DrmMockHelper::getEngineOrMemoryInstanceValue(tile, 0); queryMemoryRegionInfo->regions[1 + tile].probed_size = 2 * MemoryConstants::gigaByte; } } } break; case PRELIM_DRM_I915_QUERY_DISTANCE_INFO: { if (failDistanceInfoQuery) { return false; } auto queryDistanceInfo = reinterpret_cast(queryItem->data_ptr); switch (queryDistanceInfo->region.memory_class) { case PRELIM_I915_MEMORY_CLASS_SYSTEM: EXPECT_EQ(sizeof(prelim_drm_i915_query_distance_info), static_cast(queryItem->length)); queryDistanceInfo->distance = -1; break; case PRELIM_I915_MEMORY_CLASS_DEVICE: { EXPECT_EQ(sizeof(prelim_drm_i915_query_distance_info), static_cast(queryItem->length)); auto engineTile = DrmMockHelper::getTileFromEngineOrMemoryInstance(queryDistanceInfo->engine.engine_instance); auto memoryTile = DrmMockHelper::getTileFromEngineOrMemoryInstance(queryDistanceInfo->region.memory_instance); queryDistanceInfo->distance = (memoryTile == engineTile) ? 0 : 100; break; } default: queryItem->length = -EINVAL; break; } } break; case PRELIM_DRM_I915_QUERY_COMPUTE_SLICES: { auto >SystemInfo = rootDeviceEnvironment.getHardwareInfo()->gtSystemInfo; auto maxEuPerSubslice = gtSystemInfo.MaxEuPerSubSlice; auto maxSlices = gtSystemInfo.MaxSlicesSupported; auto maxSubslices = gtSystemInfo.MaxSubSlicesSupported / maxSlices; auto threadsPerEu = gtSystemInfo.ThreadCount / gtSystemInfo.EUCount; auto realEuCount = threadsPerEu * maxEuPerSubslice * maxSubslices * maxSlices; auto dataSize = static_cast(std::ceil(realEuCount / 8.0)) + maxSlices * static_cast(std::ceil(maxSubslices / 8.0)) + static_cast(std::ceil(maxSlices / 8.0)); if (queryItem->length == 0) { queryItem->length = static_cast(sizeof(drm_i915_query_topology_info) + dataSize); break; } else { auto topologyArg = reinterpret_cast(queryItem->data_ptr); if (failRetTopology) { return false; } topologyArg->max_slices = maxSlices; topologyArg->max_subslices = maxSubslices; topologyArg->max_eus_per_subslice = maxEuPerSubslice; topologyArg->subslice_stride = static_cast(std::ceil(maxSubslices / 8.0)); topologyArg->eu_stride = static_cast(std::ceil(maxEuPerSubslice / 8.0)); topologyArg->subslice_offset = static_cast(std::ceil(maxSlices / 8.0)); topologyArg->eu_offset = static_cast(std::ceil(maxSubslices / 8.0)) * maxSlices; int threadData = (threadsPerEu == 8) ? 0xff : 0x7f; uint8_t *data = topologyArg->data; for (uint32_t sliceId = 0; sliceId < maxSlices; sliceId++) { data[0] |= 1 << (sliceId % 8); if (sliceId == 7 || sliceId == maxSlices - 1) { data++; } } DEBUG_BREAK_IF(ptrDiff(data, topologyArg->data) != topologyArg->subslice_offset); data = ptrOffset(topologyArg->data, topologyArg->subslice_offset); for (uint32_t sliceId = 0; sliceId < maxSlices; sliceId++) { for (uint32_t i = 0; i < maxSubslices; i++) { data[0] |= 1 << (i % 8); if (i == 7 || i == maxSubslices - 1) { data++; } } } DEBUG_BREAK_IF(ptrDiff(data, topologyArg->data) != topologyArg->eu_offset); auto size = dataSize - topologyArg->eu_offset; memset(ptrOffset(topologyArg->data, topologyArg->eu_offset), threadData, size); } } break; default: queryItem->length = -EINVAL; break; } return true; } uint32_t DrmPrelimHelper::getQueryComputeSlicesIoctl() { return PRELIM_DRM_I915_QUERY_COMPUTE_SLICES; } uint32_t DrmPrelimHelper::getDistanceInfoQueryId() { return PRELIM_DRM_I915_QUERY_DISTANCE_INFO; } uint32_t DrmPrelimHelper::getComputeEngineClass() { return PRELIM_I915_ENGINE_CLASS_COMPUTE; }