diff --git a/level_zero/sysman/source/api/global_operations/windows/sysman_os_global_operations_imp.cpp b/level_zero/sysman/source/api/global_operations/windows/sysman_os_global_operations_imp.cpp index f71aed1ef0..db3ab630d8 100644 --- a/level_zero/sysman/source/api/global_operations/windows/sysman_os_global_operations_imp.cpp +++ b/level_zero/sysman/source/api/global_operations/windows/sysman_os_global_operations_imp.cpp @@ -7,6 +7,9 @@ #include "level_zero/sysman/source/api/global_operations/windows/sysman_os_global_operations_imp.h" +#include "shared/source/helpers/gfx_core_helper.h" +#include "shared/source/os_interface/os_interface.h" + namespace L0 { namespace Sysman { @@ -35,9 +38,76 @@ void WddmGlobalOperationsImp::getWedgedStatus(zes_device_state_t *pState) { void WddmGlobalOperationsImp::getRepairStatus(zes_device_state_t *pState) { } bool WddmGlobalOperationsImp::getUuid(std::array &uuid) { - return false; + if (pWddmSysmanImp->getSysmanDeviceImp()->getRootDeviceEnvironment().osInterface != nullptr) { + auto driverModel = pWddmSysmanImp->getSysmanDeviceImp()->getRootDeviceEnvironment().osInterface->getDriverModel(); + auto &gfxCoreHelper = pWddmSysmanImp->getSysmanDeviceImp()->getRootDeviceEnvironment().getHelper(); + auto &productHelper = pWddmSysmanImp->getSysmanDeviceImp()->getRootDeviceEnvironment().getHelper(); + auto subDeviceCount = pWddmSysmanImp->getSubDeviceCount(); + if (NEO::DebugManager.flags.EnableChipsetUniqueUUID.get() != 0) { + if (gfxCoreHelper.isChipsetUniqueUUIDSupported()) { + this->uuid.isValid = productHelper.getUuid(driverModel, subDeviceCount, 0u, this->uuid.id); + } + } + + if (!this->uuid.isValid) { + NEO::PhysicalDevicePciBusInfo pciBusInfo = driverModel->getPciBusInfo(); + this->uuid.isValid = generateUuidFromPciBusInfo(pciBusInfo, this->uuid.id); + } + + if (this->uuid.isValid) { + uuid = this->uuid.id; + } + } + + return this->uuid.isValid; } + bool WddmGlobalOperationsImp::generateUuidFromPciBusInfo(const NEO::PhysicalDevicePciBusInfo &pciBusInfo, std::array &uuid) { + if (pciBusInfo.pciDomain != NEO::PhysicalDevicePciBusInfo::invalidValue) { + uuid.fill(0); + + // Device UUID uniquely identifies a device within a system. + // We generate it based on device information along with PCI information + // This guarantees uniqueness of UUIDs on a system even when multiple + // identical Intel GPUs are present. + // + + // We want to have UUID matching between different GPU APIs (including outside + // of compute_runtime project - i.e. other than L0 or OCL). This structure definition + // has been agreed upon by various Intel driver teams. + // + // Consult other driver teams before changing this. + // + + struct DeviceUUID { + uint16_t vendorID; + uint16_t deviceID; + uint16_t revisionID; + uint16_t pciDomain; + uint8_t pciBus; + uint8_t pciDev; + uint8_t pciFunc; + uint8_t reserved[4]; + uint8_t subDeviceID; + }; + + auto &hwInfo = pWddmSysmanImp->getSysmanDeviceImp()->getHardwareInfo(); + DeviceUUID deviceUUID = {}; + deviceUUID.vendorID = 0x8086; // Intel + deviceUUID.deviceID = hwInfo.platform.usDeviceID; + deviceUUID.revisionID = hwInfo.platform.usRevId; + deviceUUID.pciDomain = static_cast(pciBusInfo.pciDomain); + deviceUUID.pciBus = static_cast(pciBusInfo.pciBus); + deviceUUID.pciDev = static_cast(pciBusInfo.pciDevice); + deviceUUID.pciFunc = static_cast(pciBusInfo.pciFunction); + deviceUUID.subDeviceID = 0; + + static_assert(sizeof(DeviceUUID) == NEO::ProductHelper::uuidSize); + + memcpy_s(uuid.data(), NEO::ProductHelper::uuidSize, &deviceUUID, sizeof(DeviceUUID)); + + return true; + } return false; } ze_result_t WddmGlobalOperationsImp::reset(ze_bool_t force) { @@ -66,7 +136,7 @@ ze_result_t WddmGlobalOperationsImp::deviceGetState(zes_device_state_t *pState) } WddmGlobalOperationsImp::WddmGlobalOperationsImp(OsSysman *pOsSysman) { - WddmSysmanImp *pWddmSysmanImp = static_cast(pOsSysman); + pWddmSysmanImp = static_cast(pOsSysman); pKmdSysManager = &pWddmSysmanImp->getKmdSysManager(); } diff --git a/level_zero/sysman/source/api/global_operations/windows/sysman_os_global_operations_imp.h b/level_zero/sysman/source/api/global_operations/windows/sysman_os_global_operations_imp.h index 4419df863d..9c7b31502c 100644 --- a/level_zero/sysman/source/api/global_operations/windows/sysman_os_global_operations_imp.h +++ b/level_zero/sysman/source/api/global_operations/windows/sysman_os_global_operations_imp.h @@ -36,8 +36,14 @@ class WddmGlobalOperationsImp : public OsGlobalOperations, NEO::NonCopyableOrMov WddmGlobalOperationsImp() = default; ~WddmGlobalOperationsImp() override = default; + struct { + bool isValid = false; + std::array id; + } uuid; + protected: KmdSysManager *pKmdSysManager = nullptr; + WddmSysmanImp *pWddmSysmanImp = nullptr; }; } // namespace Sysman diff --git a/level_zero/sysman/test/unit_tests/sources/global_operations/windows/test_zes_global_operations.cpp b/level_zero/sysman/test/unit_tests/sources/global_operations/windows/test_zes_global_operations.cpp index 48db96eab9..0fd96620a7 100644 --- a/level_zero/sysman/test/unit_tests/sources/global_operations/windows/test_zes_global_operations.cpp +++ b/level_zero/sysman/test/unit_tests/sources/global_operations/windows/test_zes_global_operations.cpp @@ -5,6 +5,9 @@ * */ +#include "shared/test/common/mocks/mock_product_helper.h" +#include "shared/test/common/test_macros/hw_test.h" + #include "level_zero/sysman/source/api/global_operations/windows/sysman_os_global_operations_imp.h" #include "level_zero/sysman/test/unit_tests/sources/global_operations/windows/mock_global_operations.h" #include "level_zero/sysman/test/unit_tests/sources/windows/mock_sysman_fixture.h" @@ -80,6 +83,109 @@ TEST_F(SysmanGlobalOperationsFixture, GivenDeviceInUseWhenCallingzesDeviceResetE EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, result); } +class SysmanGlobalOperationsUuidFixture : public SysmanDeviceFixture { + public: + L0::Sysman::GlobalOperationsImp *pGlobalOperationsImp; + L0::Sysman::SysmanDeviceImp *device = nullptr; + void SetUp() override { + SysmanDeviceFixture::SetUp(); + pGlobalOperationsImp = static_cast(pSysmanDeviceImp->pGlobalOperations); + device = pSysmanDeviceImp; + } + + void TearDown() override { + SysmanDeviceFixture::TearDown(); + } + + void initGlobalOps() { + zes_device_state_t deviceState; + zesDeviceGetState(device, &deviceState); + } +}; + +struct MockGlobalOperationsProductHelper : public ProductHelperHw { + MockGlobalOperationsProductHelper() = default; + bool getUuid(DriverModel *driverModel, const uint32_t subDeviceCount, const uint32_t deviceIndex, std::array &uuid) const override { + auto pDriver = driverModel->as(); + if (pDriver) { + uint64_t mockUuidValue = 0x12345678; + uuid.fill(0); + memcpy_s(uuid.data(), uuid.size(), &mockUuidValue, sizeof(mockUuidValue)); + return true; + } + + return false; + } +}; + +HWTEST2_F(SysmanGlobalOperationsUuidFixture, GivenValidDeviceHandleWhenRetrievingUuidThenValidUuidIsReturned, IsDG2) { + initGlobalOps(); + uint64_t expectedUuidValue = 0x12345678; + + std::unique_ptr mockProductHelper = std::make_unique(); + auto &rootDeviceEnvironment = (pWddmSysmanImp->getSysmanDeviceImp()->getRootDeviceEnvironmentRef()); + + std::swap(rootDeviceEnvironment.productHelper, mockProductHelper); + + std::array uuid; + bool result = pGlobalOperationsImp->pOsGlobalOperations->getUuid(uuid); + EXPECT_EQ(true, result); + uint64_t *pUuidValue = (uint64_t *)uuid.data(); + EXPECT_EQ(*pUuidValue, expectedUuidValue); + + std::swap(rootDeviceEnvironment.productHelper, mockProductHelper); +} + +TEST_F(SysmanGlobalOperationsUuidFixture, GivenValidDeviceHandleWhenCallingGenerateUuidFromPciBusInfoThenValidUuidIsReturned) { + initGlobalOps(); + + auto pHwInfo = pWddmSysmanImp->getSysmanDeviceImp()->getRootDeviceEnvironment().getMutableHardwareInfo(); + pHwInfo->platform.usDeviceID = 0x1234; + pHwInfo->platform.usRevId = 0x1; + + std::array uuid; + NEO::PhysicalDevicePciBusInfo pciBusInfo = {}; + pciBusInfo.pciDomain = 0x5678; + pciBusInfo.pciBus = 0x9; + pciBusInfo.pciDevice = 0xA; + pciBusInfo.pciFunction = 0xB; + + bool result = pGlobalOperationsImp->pOsGlobalOperations->generateUuidFromPciBusInfo(pciBusInfo, uuid); + EXPECT_EQ(true, result); + uint8_t *pUuid = (uint8_t *)uuid.data(); + EXPECT_EQ(*((uint16_t *)pUuid), (uint16_t)0x8086); + EXPECT_EQ(*((uint16_t *)(pUuid + 2)), (uint16_t)pHwInfo->platform.usDeviceID); + EXPECT_EQ(*((uint16_t *)(pUuid + 4)), (uint16_t)pHwInfo->platform.usRevId); + EXPECT_EQ(*((uint16_t *)(pUuid + 6)), (uint16_t)pciBusInfo.pciDomain); + EXPECT_EQ((*(pUuid + 8)), (uint8_t)pciBusInfo.pciBus); + EXPECT_EQ((*(pUuid + 9)), (uint8_t)pciBusInfo.pciDevice); + EXPECT_EQ((*(pUuid + 10)), (uint8_t)pciBusInfo.pciFunction); +} + +TEST_F(SysmanGlobalOperationsUuidFixture, GivenValidDeviceHandleWithInvalidPciDomainWhenCallingGenerateUuidFromPciBusInfoThenFalseIsReturned) { + initGlobalOps(); + + std::array uuid; + NEO::PhysicalDevicePciBusInfo pciBusInfo = {}; + pciBusInfo.pciDomain = std::numeric_limits::max(); + + bool result = pGlobalOperationsImp->pOsGlobalOperations->generateUuidFromPciBusInfo(pciBusInfo, uuid); + EXPECT_EQ(false, result); +} + +TEST_F(SysmanGlobalOperationsUuidFixture, GivenNullOsInterfaceObjectWhenRetrievingUuidThenFalseIsReturned) { + initGlobalOps(); + + auto &rootDeviceEnvironment = (pWddmSysmanImp->getSysmanDeviceImp()->getRootDeviceEnvironmentRef()); + auto prevOsInterface = std::move(rootDeviceEnvironment.osInterface); + rootDeviceEnvironment.osInterface = nullptr; + + std::array uuid; + bool result = pGlobalOperationsImp->pOsGlobalOperations->getUuid(uuid); + EXPECT_EQ(false, result); + rootDeviceEnvironment.osInterface = std::move(prevOsInterface); +} + } // namespace ult } // namespace Sysman } // namespace L0