diff --git a/level_zero/core/source/device/device_imp.cpp b/level_zero/core/source/device/device_imp.cpp index 845c61d6bb..7368be62a2 100644 --- a/level_zero/core/source/device/device_imp.cpp +++ b/level_zero/core/source/device/device_imp.cpp @@ -481,8 +481,10 @@ ze_result_t DeviceImp::getMemoryProperties(uint32_t *pCount, ze_device_memory_pr auto &hwInfo = this->getHwInfo(); auto &hwInfoConfig = *NEO::HwInfoConfig::get(hwInfo.platform.eProductFamily); strcpy_s(pMemProperties->name, ZE_MAX_DEVICE_NAME, hwInfoConfig.getDeviceMemoryName().c_str()); - pMemProperties->maxClockRate = hwInfoConfig.getDeviceMemoryMaxClkRate(hwInfo); + auto osInterface = neoDevice->getRootDeviceEnvironment().osInterface.get(); + pMemProperties->maxClockRate = hwInfoConfig.getDeviceMemoryMaxClkRate(hwInfo, osInterface, 0); pMemProperties->maxBusWidth = deviceInfo.addressBits; + if (this->isImplicitScalingCapable() || this->getNEODevice()->getNumGenericSubDevices() == 0) { pMemProperties->totalSize = deviceInfo.globalMemSize; @@ -491,6 +493,38 @@ ze_result_t DeviceImp::getMemoryProperties(uint32_t *pCount, ze_device_memory_pr } pMemProperties->flags = 0; + + void *pNext = pMemProperties->pNext; + while (pNext) { + auto extendedProperties = reinterpret_cast(pMemProperties->pNext); + if (extendedProperties->stype == ZE_STRUCTURE_TYPE_DEVICE_MEMORY_EXT_PROPERTIES) { + + // GT_MEMORY_TYPES map to ze_device_memory_ext_type_t + const std::array sysInfoMemType = { + ZE_DEVICE_MEMORY_EXT_TYPE_LPDDR4, + ZE_DEVICE_MEMORY_EXT_TYPE_LPDDR5, + ZE_DEVICE_MEMORY_EXT_TYPE_HBM2, + ZE_DEVICE_MEMORY_EXT_TYPE_HBM2, + ZE_DEVICE_MEMORY_EXT_TYPE_GDDR6, + }; + + extendedProperties->type = sysInfoMemType[hwInfo.gtSystemInfo.MemoryType]; + + uint32_t enabledSubDeviceCount = 1; + if (this->isImplicitScalingCapable()) { + enabledSubDeviceCount = static_cast(neoDevice->getDeviceBitfield().count()); + } + extendedProperties->physicalSize = hwInfoConfig.getDeviceMemoryPhysicalSizeInBytes(osInterface, 0) * enabledSubDeviceCount; + const uint64_t bandwidthInBytesPerSecond = hwInfoConfig.getDeviceMemoryMaxBandWidthInBytesPerSecond(hwInfo, osInterface, 0) * enabledSubDeviceCount; + + // Convert to nano-seconds range + extendedProperties->readBandwidth = static_cast(bandwidthInBytesPerSecond * 1e-9); + extendedProperties->writeBandwidth = extendedProperties->readBandwidth; + extendedProperties->bandwidthUnit = ZE_BANDWIDTH_UNIT_BYTES_PER_NANOSEC; + } + pNext = const_cast(extendedProperties->pNext); + } + return ZE_RESULT_SUCCESS; } diff --git a/level_zero/core/test/unit_tests/sources/device/test_device.cpp b/level_zero/core/test/unit_tests/sources/device/test_device.cpp index 070eb4e532..8c919d6695 100644 --- a/level_zero/core/test/unit_tests/sources/device/test_device.cpp +++ b/level_zero/core/test/unit_tests/sources/device/test_device.cpp @@ -10,6 +10,7 @@ #include "shared/source/device/root_device.h" #include "shared/source/helpers/bindless_heaps_helper.h" #include "shared/source/helpers/hw_helper.h" +#include "shared/source/helpers/hw_info.h" #include "shared/source/helpers/preamble.h" #include "shared/source/os_interface/hw_info_config.h" #include "shared/source/os_interface/os_inc_base.h" @@ -1546,15 +1547,63 @@ TEST_F(DeviceGetMemoryTests, whenCallingGetMemoryPropertiesWithNonNullPtrThenPro res = device->getMemoryProperties(&count, &memProperties); EXPECT_EQ(res, ZE_RESULT_SUCCESS); EXPECT_EQ(1u, count); - auto hwInfo = *NEO::defaultHwInfo; auto &hwInfoConfig = *NEO::HwInfoConfig::get(hwInfo.platform.eProductFamily); - EXPECT_EQ(memProperties.maxClockRate, hwInfoConfig.getDeviceMemoryMaxClkRate(hwInfo)); + EXPECT_EQ(memProperties.maxClockRate, hwInfoConfig.getDeviceMemoryMaxClkRate(hwInfo, nullptr, 0)); EXPECT_EQ(memProperties.maxBusWidth, this->neoDevice->getDeviceInfo().addressBits); EXPECT_EQ(memProperties.totalSize, this->neoDevice->getDeviceInfo().globalMemSize); EXPECT_EQ(0u, memProperties.flags); } +HWTEST2_F(DeviceGetMemoryTests, whenCallingGetMemoryPropertiesForMemoryExtPropertiesThenPropertiesAreReturned, MatchAny) { + uint32_t count = 0; + ze_result_t res = device->getMemoryProperties(&count, nullptr); + EXPECT_EQ(res, ZE_RESULT_SUCCESS); + EXPECT_EQ(1u, count); + + auto hwInfo = *NEO::defaultHwInfo; + MockHwInfoConfigHw hwInfoConfig; + VariableBackup hwInfoConfigFactoryBackup{&NEO::hwInfoConfigFactory[static_cast(hwInfo.platform.eProductFamily)]}; + hwInfoConfigFactoryBackup = &hwInfoConfig; + + ze_device_memory_properties_t memProperties = {}; + ze_device_memory_ext_properties_t memExtProperties = {}; + memExtProperties.stype = ZE_STRUCTURE_TYPE_DEVICE_MEMORY_EXT_PROPERTIES; + memProperties.pNext = &memExtProperties; + res = device->getMemoryProperties(&count, &memProperties); + EXPECT_EQ(res, ZE_RESULT_SUCCESS); + EXPECT_EQ(1u, count); + const std::array sysInfoMemType = { + ZE_DEVICE_MEMORY_EXT_TYPE_LPDDR4, + ZE_DEVICE_MEMORY_EXT_TYPE_LPDDR5, + ZE_DEVICE_MEMORY_EXT_TYPE_HBM2, + ZE_DEVICE_MEMORY_EXT_TYPE_HBM2, + ZE_DEVICE_MEMORY_EXT_TYPE_GDDR6, + }; + + auto bandwidthPerNanoSecond = hwInfoConfig.getDeviceMemoryMaxBandWidthInBytesPerSecond(hwInfo, nullptr, 0) / 1000000000; + + EXPECT_EQ(memExtProperties.type, sysInfoMemType[hwInfo.gtSystemInfo.MemoryType]); + EXPECT_EQ(memExtProperties.physicalSize, hwInfoConfig.getDeviceMemoryPhysicalSizeInBytes(nullptr, 0)); + EXPECT_EQ(memExtProperties.readBandwidth, bandwidthPerNanoSecond); + EXPECT_EQ(memExtProperties.writeBandwidth, memExtProperties.readBandwidth); + EXPECT_EQ(memExtProperties.bandwidthUnit, ZE_BANDWIDTH_UNIT_BYTES_PER_NANOSEC); +} + +TEST_F(DeviceGetMemoryTests, whenCallingGetMemoryPropertiesWhenPnextIsNonNullAndStypeIsUnSupportedThenNoErrorIsReturned) { + uint32_t count = 0; + ze_result_t res = device->getMemoryProperties(&count, nullptr); + EXPECT_EQ(res, ZE_RESULT_SUCCESS); + EXPECT_EQ(1u, count); + + ze_device_memory_properties_t memProperties = {}; + ze_device_memory_ext_properties_t memExtProperties = {}; + memExtProperties.stype = ZE_STRUCTURE_TYPE_FORCE_UINT32; + memProperties.pNext = &memExtProperties; + res = device->getMemoryProperties(&count, &memProperties); + EXPECT_EQ(res, ZE_RESULT_SUCCESS); +} + struct DeviceHasNoDoubleFp64Test : public ::testing::Test { void SetUp() override { DebugManager.flags.CreateMultipleRootDevices.set(numRootDevices); @@ -1885,6 +1934,42 @@ TEST_F(MultipleDevicesEnabledImplicitScalingTest, GivenImplicitScalingEnabledWhe EXPECT_EQ((gtSysInfo.SliceCount * numSubDevices), deviceProperties.numSlices); } +HWTEST2_F(MultipleDevicesEnabledImplicitScalingTest, GivenImplicitScalingEnabledDeviceWhenCallingGetMemoryPropertiesForMemoryExtPropertiesThenPropertiesAreReturned, MatchAny) { + uint32_t count = 0; + L0::Device *device = driverHandle->devices[0]; + auto hwInfo = *NEO::defaultHwInfo; + ze_result_t res = device->getMemoryProperties(&count, nullptr); + EXPECT_EQ(res, ZE_RESULT_SUCCESS); + EXPECT_EQ(1u, count); + + MockHwInfoConfigHw hwInfoConfig; + VariableBackup hwInfoConfigFactoryBackup{&NEO::hwInfoConfigFactory[static_cast(hwInfo.platform.eProductFamily)]}; + hwInfoConfigFactoryBackup = &hwInfoConfig; + + ze_device_memory_properties_t memProperties = {}; + ze_device_memory_ext_properties_t memExtProperties = {}; + memExtProperties.stype = ZE_STRUCTURE_TYPE_DEVICE_MEMORY_EXT_PROPERTIES; + memProperties.pNext = &memExtProperties; + res = device->getMemoryProperties(&count, &memProperties); + EXPECT_EQ(res, ZE_RESULT_SUCCESS); + EXPECT_EQ(1u, count); + const std::array sysInfoMemType = { + ZE_DEVICE_MEMORY_EXT_TYPE_LPDDR4, + ZE_DEVICE_MEMORY_EXT_TYPE_LPDDR5, + ZE_DEVICE_MEMORY_EXT_TYPE_HBM2, + ZE_DEVICE_MEMORY_EXT_TYPE_HBM2, + ZE_DEVICE_MEMORY_EXT_TYPE_GDDR6, + }; + + auto bandwidthPerNanoSecond = hwInfoConfig.getDeviceMemoryMaxBandWidthInBytesPerSecond(hwInfo, nullptr, 0) / 1000000000; + + EXPECT_EQ(memExtProperties.type, sysInfoMemType[hwInfo.gtSystemInfo.MemoryType]); + EXPECT_EQ(memExtProperties.physicalSize, hwInfoConfig.getDeviceMemoryPhysicalSizeInBytes(nullptr, 0) * numSubDevices); + EXPECT_EQ(memExtProperties.readBandwidth, bandwidthPerNanoSecond * numSubDevices); + EXPECT_EQ(memExtProperties.writeBandwidth, memExtProperties.readBandwidth); + EXPECT_EQ(memExtProperties.bandwidthUnit, ZE_BANDWIDTH_UNIT_BYTES_PER_NANOSEC); +} + TEST_F(MultipleDevicesTest, whenRetrievingNumberOfSubdevicesThenCorrectNumberIsReturned) { L0::Device *device0 = driverHandle->devices[0]; @@ -3300,7 +3385,7 @@ TEST_F(DeviceSimpleTests, WhenGettingKernelPropertiesThenSuccessIsReturned) { } TEST_F(DeviceSimpleTests, WhenGettingMemoryPropertiesThenSuccessIsReturned) { - ze_device_memory_properties_t properties; + ze_device_memory_properties_t properties = {}; uint32_t count = 1; auto result = device->getMemoryProperties(&count, &properties); EXPECT_EQ(ZE_RESULT_SUCCESS, result); diff --git a/level_zero/core/test/unit_tests/xe_hpc_core/pvc/test_device_pvc.cpp b/level_zero/core/test/unit_tests/xe_hpc_core/pvc/test_device_pvc.cpp index b7c227f75d..ac39292976 100644 --- a/level_zero/core/test/unit_tests/xe_hpc_core/pvc/test_device_pvc.cpp +++ b/level_zero/core/test/unit_tests/xe_hpc_core/pvc/test_device_pvc.cpp @@ -51,22 +51,6 @@ PVCTEST_F(DeviceTestPvc, givenPvcAStepWhenCreatingMultiTileDeviceThenExpectImpli delete device; } -PVCTEST_F(DeviceTestPvc, whenCallingGetMemoryPropertiesWithNonNullPtrThenPropertiesAreReturned) { - uint32_t count = 0; - ze_result_t res = device->getMemoryProperties(&count, nullptr); - EXPECT_EQ(res, ZE_RESULT_SUCCESS); - EXPECT_EQ(1u, count); - - ze_device_memory_properties_t memProperties = {}; - res = device->getMemoryProperties(&count, &memProperties); - EXPECT_EQ(res, ZE_RESULT_SUCCESS); - EXPECT_EQ(1u, count); - - EXPECT_EQ(memProperties.maxClockRate, 3200u); - EXPECT_EQ(memProperties.maxBusWidth, this->neoDevice->getDeviceInfo().addressBits); - EXPECT_EQ(memProperties.totalSize, this->neoDevice->getDeviceInfo().globalMemSize); -} - PVCTEST_F(DeviceTestPvc, GivenPvcWhenGettingPhysicalEuSimdWidthThenReturn16) { ze_device_properties_t properties = {ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES}; device->getProperties(&properties); diff --git a/shared/source/os_interface/hw_info_config.h b/shared/source/os_interface/hw_info_config.h index a585643ef9..cccd7f93ba 100644 --- a/shared/source/os_interface/hw_info_config.h +++ b/shared/source/os_interface/hw_info_config.h @@ -50,7 +50,9 @@ class HwInfoConfig { virtual void getKernelExtendedProperties(uint32_t *fp16, uint32_t *fp32, uint32_t *fp64) = 0; virtual std::vector getKernelSupportedThreadArbitrationPolicies() = 0; virtual void convertTimestampsFromOaToCsDomain(uint64_t ×tampData) = 0; - virtual uint32_t getDeviceMemoryMaxClkRate(const HardwareInfo &hwInfo) = 0; + virtual uint32_t getDeviceMemoryMaxClkRate(const HardwareInfo &hwInfo, const OSInterface *osIface, uint32_t subDeviceIndex) = 0; + virtual uint64_t getDeviceMemoryPhysicalSizeInBytes(const OSInterface *osIface, uint32_t subDeviceIndex) = 0; + virtual uint64_t getDeviceMemoryMaxBandWidthInBytesPerSecond(const HardwareInfo &hwInfo, const OSInterface *osIface, uint32_t subDeviceIndex) = 0; virtual bool isAdditionalStateBaseAddressWARequired(const HardwareInfo &hwInfo) const = 0; virtual bool isMaxThreadsForWorkgroupWARequired(const HardwareInfo &hwInfo) const = 0; virtual uint32_t getMaxThreadsForWorkgroupInDSSOrSS(const HardwareInfo &hwInfo, uint32_t maxNumEUsPerSubSlice, uint32_t maxNumEUsPerDualSubSlice) const = 0; @@ -148,7 +150,9 @@ class HwInfoConfigHw : public HwInfoConfig { void getKernelExtendedProperties(uint32_t *fp16, uint32_t *fp32, uint32_t *fp64) override; std::vector getKernelSupportedThreadArbitrationPolicies() override; void convertTimestampsFromOaToCsDomain(uint64_t ×tampData) override; - uint32_t getDeviceMemoryMaxClkRate(const HardwareInfo &hwInfo) override; + uint32_t getDeviceMemoryMaxClkRate(const HardwareInfo &hwInfo, const OSInterface *osIface, uint32_t subDeviceIndex) override; + uint64_t getDeviceMemoryPhysicalSizeInBytes(const OSInterface *osIface, uint32_t subDeviceIndex) override; + uint64_t getDeviceMemoryMaxBandWidthInBytesPerSecond(const HardwareInfo &hwInfo, const OSInterface *osIface, uint32_t subDeviceIndex) override; bool isAdditionalStateBaseAddressWARequired(const HardwareInfo &hwInfo) const override; bool isMaxThreadsForWorkgroupWARequired(const HardwareInfo &hwInfo) const override; uint32_t getMaxThreadsForWorkgroupInDSSOrSS(const HardwareInfo &hwInfo, uint32_t maxNumEUsPerSubSlice, uint32_t maxNumEUsPerDualSubSlice) const override; diff --git a/shared/source/os_interface/hw_info_config.inl b/shared/source/os_interface/hw_info_config.inl index 4313fa6c89..6f43ff287e 100644 --- a/shared/source/os_interface/hw_info_config.inl +++ b/shared/source/os_interface/hw_info_config.inl @@ -95,10 +95,20 @@ uint64_t HwInfoConfigHw::getSharedSystemMemCapabilities(const Hardwa } template -uint32_t HwInfoConfigHw::getDeviceMemoryMaxClkRate(const HardwareInfo &hwInfo) { +uint32_t HwInfoConfigHw::getDeviceMemoryMaxClkRate(const HardwareInfo &hwInfo, const OSInterface *osIface, uint32_t subDeviceIndex) { return 0u; } +template +uint64_t HwInfoConfigHw::getDeviceMemoryPhysicalSizeInBytes(const OSInterface *osIface, uint32_t subDeviceIndex) { + return 0; +} + +template +uint64_t HwInfoConfigHw::getDeviceMemoryMaxBandWidthInBytesPerSecond(const HardwareInfo &hwInfo, const OSInterface *osIface, uint32_t subDeviceIndex) { + return 0; +} + template bool HwInfoConfigHw::isAdditionalStateBaseAddressWARequired(const HardwareInfo &hwInfo) const { return false; diff --git a/shared/source/os_interface/linux/drm_neo.cpp b/shared/source/os_interface/linux/drm_neo.cpp index 498683a984..5f042f3427 100644 --- a/shared/source/os_interface/linux/drm_neo.cpp +++ b/shared/source/os_interface/linux/drm_neo.cpp @@ -171,6 +171,29 @@ std::string Drm::getSysFsPciPath() { return {}; } +bool Drm::readSysFsAsString(const std::string &relativeFilePath, std::string &readString) { + + auto devicePath = getSysFsPciPath(); + if (devicePath.empty()) { + return false; + } + + const std::string fileName = devicePath + relativeFilePath; + int fd = SysCalls::open(fileName.c_str(), O_RDONLY); + if (fd < 0) { + return false; + } + + ssize_t bytesRead = SysCalls::pread(fd, readString.data(), readString.size() - 1, 0); + NEO::SysCalls::close(fd); + if (bytesRead <= 0) { + return false; + } + + std::replace(readString.begin(), readString.end(), '\n', '\0'); + return true; +} + int Drm::queryGttSize(uint64_t >tSizeOutput) { GemContextParam contextParam = {0}; contextParam.param = I915_CONTEXT_PARAM_GTT_SIZE; @@ -806,6 +829,40 @@ int Drm::getMaxGpuFrequency(HardwareInfo &hwInfo, int &maxGpuFrequency) { return getMaxGpuFrequencyOfDevice(*this, sysFsPciPath, maxGpuFrequency); } +bool Drm::getDeviceMemoryMaxClockRateInMhz(uint32_t tileId, uint32_t &clkRate) { + const std::string relativefilePath = "/gt/gt" + std::to_string(tileId) + "/mem_RP0_freq_mhz"; + std::string readString(64, '\0'); + errno = 0; + if (readSysFsAsString(relativefilePath, readString) == false) { + return false; + } + + char *endPtr = nullptr; + uint32_t retClkRate = static_cast(std::strtoul(readString.data(), &endPtr, 10)); + if ((endPtr == readString.data()) || (errno != 0)) { + return false; + } + clkRate = retClkRate; + return true; +} + +bool Drm::getDeviceMemoryPhysicalSizeInBytes(uint32_t tileId, uint64_t &physicalSize) { + const std::string relativefilePath = "/gt/gt" + std::to_string(tileId) + "/addr_range"; + std::string readString(64, '\0'); + errno = 0; + if (readSysFsAsString(relativefilePath, readString) == false) { + return false; + } + + char *endPtr = nullptr; + uint64_t retSize = static_cast(std::strtoull(readString.data(), &endPtr, 16)); + if ((endPtr == readString.data()) || (errno != 0)) { + return false; + } + physicalSize = retSize; + return true; +} + bool Drm::useVMBindImmediate() const { bool useBindImmediate = isDirectSubmissionActive() || hasPageFaultSupport(); diff --git a/shared/source/os_interface/linux/drm_neo.h b/shared/source/os_interface/linux/drm_neo.h index e8499daff2..74e44c3f22 100644 --- a/shared/source/os_interface/linux/drm_neo.h +++ b/shared/source/os_interface/linux/drm_neo.h @@ -249,6 +249,8 @@ class Drm : public DriverModel { uint64_t getPatIndex(Gmm *gmm, AllocationType allocationType, CacheRegion cacheRegion, CachePolicy cachePolicy, bool closEnabled) const; bool isVmBindPatIndexProgrammingSupported() const { return vmBindPatIndexProgrammingSupported; } + MOCKABLE_VIRTUAL bool getDeviceMemoryMaxClockRateInMhz(uint32_t tileId, uint32_t &clkRate); + MOCKABLE_VIRTUAL bool getDeviceMemoryPhysicalSizeInBytes(uint32_t tileId, uint64_t &physicalSize); protected: Drm(std::unique_ptr &&hwDeviceIdIn, RootDeviceEnvironment &rootDeviceEnvironment); @@ -265,6 +267,7 @@ class Drm : public DriverModel { static std::string getDrmVersion(int fileDescriptor); bool queryDeviceIdAndRevision(); bool queryI915DeviceIdAndRevision(); + bool readSysFsAsString(const std::string &filePath, std::string &readString); #pragma pack(1) struct PCIConfig { diff --git a/shared/source/xe_hp_core/linux/hw_info_config_xe_hp_sdv.cpp b/shared/source/xe_hp_core/linux/hw_info_config_xe_hp_sdv.cpp index a73cb6f38e..c727e2c8cd 100644 --- a/shared/source/xe_hp_core/linux/hw_info_config_xe_hp_sdv.cpp +++ b/shared/source/xe_hp_core/linux/hw_info_config_xe_hp_sdv.cpp @@ -75,7 +75,7 @@ void HwInfoConfigHw::getKernelExtendedProperties(uint32_t *fp16, uin } template <> -uint32_t HwInfoConfigHw::getDeviceMemoryMaxClkRate(const HardwareInfo &hwInfo) { +uint32_t HwInfoConfigHw::getDeviceMemoryMaxClkRate(const HardwareInfo &hwInfo, const OSInterface *osIface, uint32_t subDeviceIndex) { return 2800u; } diff --git a/shared/source/xe_hp_core/windows/hw_info_config_xe_hp_sdv.cpp b/shared/source/xe_hp_core/windows/hw_info_config_xe_hp_sdv.cpp index 762ad833f9..651db28bee 100644 --- a/shared/source/xe_hp_core/windows/hw_info_config_xe_hp_sdv.cpp +++ b/shared/source/xe_hp_core/windows/hw_info_config_xe_hp_sdv.cpp @@ -53,10 +53,5 @@ void HwInfoConfigHw::getKernelExtendedProperties(uint32_t *fp16, uin *fp64 = 0u; } -template <> -uint32_t HwInfoConfigHw::getDeviceMemoryMaxClkRate(const HardwareInfo &hwInfo) { - return 2800u; -} - template class HwInfoConfigHw; } // namespace NEO diff --git a/shared/source/xe_hpc_core/linux/hw_info_config_pvc.cpp b/shared/source/xe_hpc_core/linux/hw_info_config_pvc.cpp index b3685034d8..7c493c9628 100644 --- a/shared/source/xe_hpc_core/linux/hw_info_config_pvc.cpp +++ b/shared/source/xe_hpc_core/linux/hw_info_config_pvc.cpp @@ -55,5 +55,44 @@ int HwInfoConfigHw::configureHardwareCustom(HardwareInfo *hwInfo, OS return 0; } +template <> +uint64_t HwInfoConfigHw::getDeviceMemoryPhysicalSizeInBytes(const OSInterface *osIface, uint32_t subDeviceIndex) { + + if (osIface == nullptr) { + return 0; + } + auto pDrm = osIface->getDriverModel()->as(); + uint64_t memoryPhysicalSize = 0; + if (pDrm->getDeviceMemoryPhysicalSizeInBytes(subDeviceIndex, memoryPhysicalSize) == false) { + return 0; + } + + return memoryPhysicalSize; +} + +template <> +uint32_t HwInfoConfigHw::getDeviceMemoryMaxClkRate(const HardwareInfo &hwInfo, const OSInterface *osIface, uint32_t subDeviceIndex) { + + if (osIface == nullptr) { + return 0; + } + + auto pDrm = osIface->getDriverModel()->as(); + uint32_t memoryMaxClkRateInMhz = 0; + if (pDrm->getDeviceMemoryMaxClockRateInMhz(subDeviceIndex, memoryMaxClkRateInMhz) == false) { + return 0; + } + + return memoryMaxClkRateInMhz; +} + +template <> +uint64_t HwInfoConfigHw::getDeviceMemoryMaxBandWidthInBytesPerSecond(const HardwareInfo &hwInfo, const OSInterface *osIface, uint32_t subDeviceIndex) { + uint64_t memoryMaxClkRateInMhz = getDeviceMemoryMaxClkRate(hwInfo, osIface, subDeviceIndex); + const uint64_t numberOfHbmStacksPerTile = 4u; + const uint64_t memoryBusWidth = 128u; + return memoryMaxClkRateInMhz * 1000 * 1000 * numberOfHbmStacksPerTile * memoryBusWidth / 8; +} + template class HwInfoConfigHw; } // namespace NEO diff --git a/shared/source/xe_hpc_core/pvc/os_agnostic_hw_info_config_pvc.inl b/shared/source/xe_hpc_core/pvc/os_agnostic_hw_info_config_pvc.inl index 97fefc5d05..5dfb53dd5a 100644 --- a/shared/source/xe_hpc_core/pvc/os_agnostic_hw_info_config_pvc.inl +++ b/shared/source/xe_hpc_core/pvc/os_agnostic_hw_info_config_pvc.inl @@ -116,16 +116,6 @@ bool isBaseDieA0(const HardwareInfo &hwInfo) { return (hwInfo.platform.usRevId & PVC::pvcBaseDieRevMask) == PVC::pvcBaseDieA0Masked; } -template <> -uint32_t HwInfoConfigHw::getDeviceMemoryMaxClkRate(const HardwareInfo &hwInfo) { - bool isDieA0 = isBaseDieA0(hwInfo); - if (isDieA0) { - // For IGFX_PVC REV A0 HBM frequency would be 3.2 GT/s = 3.2 * 1000 MT/s = 3200 MT/s - return 3200u; - } - return 0u; -} - template <> bool HwInfoConfigHw::isTilePlacementResourceWaRequired(const HardwareInfo &hwInfo) const { bool baseDieA0 = isBaseDieA0(hwInfo); diff --git a/shared/test/common/helpers/mock_hw_info_config_hw.h b/shared/test/common/helpers/mock_hw_info_config_hw.h index a29c370154..69c4f2c8bf 100644 --- a/shared/test/common/helpers/mock_hw_info_config_hw.h +++ b/shared/test/common/helpers/mock_hw_info_config_hw.h @@ -18,6 +18,8 @@ struct MockHwInfoConfigHw : NEO::HwInfoConfigHw { bool getUuid(Device *device, std::array &uuid) const override; uint32_t getSteppingFromHwRevId(const HardwareInfo &hwInfo) const override; int configureHardwareCustom(HardwareInfo *hwInfo, OSInterface *osIface) override; + uint64_t getDeviceMemoryPhysicalSizeInBytes(const OSInterface *osIface, uint32_t subDeviceIndex) override; + uint32_t getDeviceMemoryMaxClkRate(const HardwareInfo &hwInfo, const OSInterface *osIface, uint32_t subDeviceIndex) override; bool use128MbEdram = false; bool enableMidThreadPreemption = false; diff --git a/shared/test/common/helpers/mock_hw_info_config_hw.inl b/shared/test/common/helpers/mock_hw_info_config_hw.inl index 25c514a982..f8e100f959 100644 --- a/shared/test/common/helpers/mock_hw_info_config_hw.inl +++ b/shared/test/common/helpers/mock_hw_info_config_hw.inl @@ -45,4 +45,14 @@ int MockHwInfoConfigHw::configureHardwareCustom(HardwareInfo *hwInfo featureTable->flags.ftrGpGpuMidBatchPreempt = 1; } return (failOnConfigureHardwareCustom) ? -1 : 0; -} \ No newline at end of file +} + +template <> +uint64_t MockHwInfoConfigHw::getDeviceMemoryPhysicalSizeInBytes(const OSInterface *osIface, uint32_t subDeviceIndex) { + return 1024u; +} + +template <> +uint32_t MockHwInfoConfigHw::getDeviceMemoryMaxClkRate(const HardwareInfo &hwInfo, const OSInterface *osIface, uint32_t subDeviceIndex) { + return 800u; +} diff --git a/shared/test/common/libult/linux/drm_mock.h b/shared/test/common/libult/linux/drm_mock.h index 72db499d54..70bb1b7f81 100644 --- a/shared/test/common/libult/linux/drm_mock.h +++ b/shared/test/common/libult/linux/drm_mock.h @@ -262,6 +262,33 @@ class DrmMock : public Drm { uint16_t flags; }; StackVec waitUserFenceParams; + + bool storedGetDeviceMemoryMaxClockRateInMhzStatus = true; + bool useBaseGetDeviceMemoryMaxClockRateInMhz = true; + bool getDeviceMemoryMaxClockRateInMhz(uint32_t tileId, uint32_t &clkRate) override { + + if (useBaseGetDeviceMemoryMaxClockRateInMhz == true) { + return Drm::getDeviceMemoryMaxClockRateInMhz(tileId, clkRate); + } + + if (storedGetDeviceMemoryMaxClockRateInMhzStatus == true) { + clkRate = 800; + } + return storedGetDeviceMemoryMaxClockRateInMhzStatus; + } + + bool storedGetDeviceMemoryPhysicalSizeInBytesStatus = true; + bool useBaseGetDeviceMemoryPhysicalSizeInBytes = true; + bool getDeviceMemoryPhysicalSizeInBytes(uint32_t tileId, uint64_t &physicalSize) override { + if (useBaseGetDeviceMemoryPhysicalSizeInBytes == true) { + return Drm::getDeviceMemoryPhysicalSizeInBytes(tileId, physicalSize); + } + + if (storedGetDeviceMemoryPhysicalSizeInBytesStatus == true) { + physicalSize = 1024; + } + return storedGetDeviceMemoryPhysicalSizeInBytesStatus; + } }; class DrmMockNonFailing : public DrmMock { diff --git a/shared/test/common/mocks/mock_hw_info_config.cpp b/shared/test/common/mocks/mock_hw_info_config.cpp index 259889fdad..1969422788 100644 --- a/shared/test/common/mocks/mock_hw_info_config.cpp +++ b/shared/test/common/mocks/mock_hw_info_config.cpp @@ -74,7 +74,17 @@ bool HwInfoConfigHw::overrideGfxPartitionLayoutForWsl() const { } template <> -uint32_t HwInfoConfigHw::getDeviceMemoryMaxClkRate(const HardwareInfo &hwInfo) { +uint32_t HwInfoConfigHw::getDeviceMemoryMaxClkRate(const HardwareInfo &hwInfo, const OSInterface *osIface, uint32_t subDeviceIndex) { + return 0; +} + +template <> +uint64_t HwInfoConfigHw::getDeviceMemoryPhysicalSizeInBytes(const OSInterface *osIface, uint32_t subDeviceIndex) { + return 0; +} + +template <> +uint64_t HwInfoConfigHw::getDeviceMemoryMaxBandWidthInBytesPerSecond(const HardwareInfo &hwInfo, const OSInterface *osIface, uint32_t subDeviceIndex) { return 0; } diff --git a/shared/test/unit_test/os_interface/linux/drm_tests.cpp b/shared/test/unit_test/os_interface/linux/drm_tests.cpp index 1853c4fb8a..82186ee9ff 100644 --- a/shared/test/unit_test/os_interface/linux/drm_tests.cpp +++ b/shared/test/unit_test/os_interface/linux/drm_tests.cpp @@ -16,9 +16,11 @@ #include "shared/test/common/helpers/default_hw_info.h" #include "shared/test/common/helpers/engine_descriptor_helper.h" #include "shared/test/common/helpers/test_files.h" +#include "shared/test/common/helpers/variable_backup.h" #include "shared/test/common/libult/linux/drm_mock.h" #include "shared/test/common/mocks/linux/mock_os_context_linux.h" #include "shared/test/common/mocks/mock_memory_manager.h" +#include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h" #include "gtest/gtest.h" @@ -102,6 +104,180 @@ TEST(DrmTest, GivenInvalidPciPathWhenFrequencyIsQueriedThenReturnError) { EXPECT_EQ(0, maxFrequency); } +TEST(DrmTest, GivenValidSysfsNodeWhenGetDeviceMemoryMaxClockRateInMhzIsCalledThenReturnSuccess) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + drm.setPciPath("device"); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return 1; + }); + + VariableBackup mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t { + const std::string testData("800"); + memcpy(buf, testData.data(), testData.length() + 1); + return 4; + }); + uint32_t clkRate = 0; + EXPECT_TRUE(drm.getDeviceMemoryMaxClockRateInMhz(0, clkRate)); + EXPECT_EQ(clkRate, 800u); +} + +TEST(DrmTest, GivenValidSysfsNodeWhenGetDeviceMemoryPhysicalSizeInBytesIsCalledThenReturnSuccess) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + drm.setPciPath("device"); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return 1; + }); + + VariableBackup mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t { + const std::string testData("800"); + memcpy(buf, testData.data(), testData.length() + 1); + return 4; + }); + uint64_t size = 0; + EXPECT_TRUE(drm.getDeviceMemoryPhysicalSizeInBytes(0, size)); + EXPECT_EQ(2048u, size); +} + +TEST(DrmTest, GivenInValidSysfsNodeWhenGetDeviceMemoryMaxClockRateInMhzIsCalledThenReturnSuccess) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + drm.setPciPath("device"); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return -1; + }); + + uint32_t clkRate = 0; + EXPECT_FALSE(drm.getDeviceMemoryMaxClockRateInMhz(0, clkRate)); +} + +TEST(DrmTest, GivenPciPathCouldNotBeRetrievedWhenGetDeviceMemoryPhysicalSizeInBytesIsCalledThenReturnZero) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + drm.setPciPath("InvaliDdevice"); + uint64_t size = 0; + EXPECT_FALSE(drm.getDeviceMemoryPhysicalSizeInBytes(0, size)); +} + +TEST(DrmTest, GivenInValidSysfsNodeWhenGetDeviceMemoryPhysicalSizeInBytesIsCalledThenReturnSuccess) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + drm.setPciPath("device"); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return -1; + }); + uint64_t size = 0; + EXPECT_FALSE(drm.getDeviceMemoryPhysicalSizeInBytes(0, size)); +} + +TEST(DrmTest, GivenSysfsNodeReadFailsWhenGetDeviceMemoryPhysicalSizeInBytesIsCalledThenReturnError) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + drm.setPciPath("device"); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return 1; + }); + + VariableBackup mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t { + const std::string testData("800"); + memcpy(buf, testData.data(), testData.length() + 1); + return 0; + }); + uint64_t size = 0; + EXPECT_FALSE(drm.getDeviceMemoryPhysicalSizeInBytes(0, size)); +} + +TEST(DrmTest, givenSysfsNodeReadFailsWithErrnoWhenGetDeviceMemoryPhysicalSizeInBytesIsCalledThenReturnError) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + drm.setPciPath("device"); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return 1; + }); + + VariableBackup mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t { + const std::string testData("800"); + memcpy(buf, testData.data(), testData.length() + 1); + errno = 1; + return 4; + }); + uint64_t size = 0; + EXPECT_FALSE(drm.getDeviceMemoryPhysicalSizeInBytes(0, size)); +} + +TEST(DrmTest, givenSysfsNodeReadFailsWithImproperDataWhenGetDeviceMemoryPhysicalSizeInBytesIsCalledThenReturnError) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + drm.setPciPath("device"); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return 1; + }); + + VariableBackup mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t { + const std::string testData("pqr"); + memcpy(buf, testData.data(), testData.length() + 1); + return 4; + }); + uint64_t size = 0; + EXPECT_FALSE(drm.getDeviceMemoryPhysicalSizeInBytes(0, size)); +} + +TEST(DrmTest, givenSysfsNodeReadFailsWithErrnoWhenGetDeviceMemoryMaxClockRateInMhzIsCalledThenReturnError) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + drm.setPciPath("device"); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return 1; + }); + + VariableBackup mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t { + const std::string testData("800"); + memcpy(buf, testData.data(), testData.length() + 1); + errno = 1; + return 4; + }); + uint32_t clkRate = 0; + EXPECT_FALSE(drm.getDeviceMemoryMaxClockRateInMhz(0, clkRate)); +} + +TEST(DrmTest, givenSysfsNodeReadFailsWithImproperDataWhenGetDeviceMemoryMaxClockRateInMhzIsCalledThenReturnError) { + auto executionEnvironment = std::make_unique(); + executionEnvironment->prepareRootDeviceEnvironments(1); + DrmMock drm{*executionEnvironment->rootDeviceEnvironments[0]}; + + drm.setPciPath("device"); + VariableBackup mockOpen(&SysCalls::sysCallsOpen, [](const char *pathname, int flags) -> int { + return 1; + }); + + VariableBackup mockPread(&SysCalls::sysCallsPread, [](int fd, void *buf, size_t count, off_t offset) -> ssize_t { + const std::string testData("abc"); + memcpy(buf, testData.data(), testData.length() + 1); + return 4; + }); + uint32_t clkRate = 0; + EXPECT_FALSE(drm.getDeviceMemoryMaxClockRateInMhz(0, clkRate)); +} + TEST(DrmTest, WhenGettingRevisionIdThenCorrectIdIsReturned) { auto executionEnvironment = std::make_unique(); executionEnvironment->prepareRootDeviceEnvironments(1); diff --git a/shared/test/unit_test/xe_hpc_core/pvc/linux/hw_info_config_tests_pvc.cpp b/shared/test/unit_test/xe_hpc_core/pvc/linux/hw_info_config_tests_pvc.cpp index d0ddf63a91..b4cf2c774e 100644 --- a/shared/test/unit_test/xe_hpc_core/pvc/linux/hw_info_config_tests_pvc.cpp +++ b/shared/test/unit_test/xe_hpc_core/pvc/linux/hw_info_config_tests_pvc.cpp @@ -9,7 +9,9 @@ #include "shared/source/os_interface/os_interface.h" #include "shared/test/common/fixtures/product_config_fixture.h" #include "shared/test/common/helpers/default_hw_info.h" +#include "shared/test/common/helpers/variable_backup.h" #include "shared/test/common/libult/linux/drm_mock.h" +#include "shared/test/common/os_interface/linux/sys_calls_linux_ult.h" #include "shared/test/common/xe_hpc_core/pvc/product_configs_pvc.h" #include "shared/test/unit_test/helpers/gtest_helpers.h" #include "shared/test/unit_test/os_interface/linux/hw_info_config_linux_tests.h" @@ -74,3 +76,32 @@ PVCTEST_F(ProductConfigTests, givenAotConfigWhenSetHwInfoRevisionIdForPvcThenCor EXPECT_EQ(hwInfo.platform.usRevId, aotConfig.ProductConfigID.Revision); } } + +PVCTEST_F(HwInfoConfigTestLinuxPvc, givenOsInterfaceIsNullWhenGetDeviceMemoryPhysicalSizeInBytesIsCalledThenReturnZero) { + auto hwInfoConfig = HwInfoConfig::get(productFamily); + EXPECT_EQ(0u, hwInfoConfig->getDeviceMemoryPhysicalSizeInBytes(nullptr, 0)); +} + +PVCTEST_F(HwInfoConfigTestLinuxPvc, givenOsInterfaceIsNullWhenGetDeviceMemoryMaxBandWidthInBytesPerSecondIsCalledThenReturnZero) { + auto hwInfoConfig = HwInfoConfig::get(productFamily); + auto testHwInfo = *defaultHwInfo; + testHwInfo.platform.usRevId = 0x8; + EXPECT_EQ(0u, hwInfoConfig->getDeviceMemoryMaxBandWidthInBytesPerSecond(testHwInfo, nullptr, 0)); +} + +PVCTEST_F(HwInfoConfigTestLinuxPvc, WhenGetDeviceMemoryPhysicalSizeInBytesIsCalledThenReturnSuccess) { + auto hwInfoConfig = HwInfoConfig::get(productFamily); + drm->setPciPath("device"); + drm->storedGetDeviceMemoryPhysicalSizeInBytesStatus = true; + drm->useBaseGetDeviceMemoryPhysicalSizeInBytes = false; + EXPECT_EQ(1024u, hwInfoConfig->getDeviceMemoryPhysicalSizeInBytes(osInterface, 0)); +} + +PVCTEST_F(HwInfoConfigTestLinuxPvc, WhenGetDeviceMemoryMaxBandWidthInBytesPerSecondIsCalledThenReturnSuccess) { + auto hwInfoConfig = HwInfoConfig::get(productFamily); + auto testHwInfo = *defaultHwInfo; + testHwInfo.platform.usRevId = 0x8; + drm->storedGetDeviceMemoryMaxClockRateInMhzStatus = true; + drm->useBaseGetDeviceMemoryMaxClockRateInMhz = false; + EXPECT_EQ(51200000000u, hwInfoConfig->getDeviceMemoryMaxBandWidthInBytesPerSecond(testHwInfo, osInterface, 0)); +}