/* * Copyright (C) 2014-2018 Advanced Micro Devices, Inc. All Rights Reserved. * * 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. * */ #include "KFDTopologyTest.hpp" #include #include const HSAuint64 KFDTopologyTest::c_4Gigabyte = (1ull << 32) - 1; const HSAuint64 KFDTopologyTest::c_40BitAddressSpace = (1ull << 40); TEST_F(KFDTopologyTest , BasicTest) { TEST_START(TESTPROFILE_RUNALL) const HsaNodeProperties *pNodeProperties; // Goes over all nodes in the sytem properties and check the basic info received for (unsigned node = 0; node < m_SystemProperties.NumNodes; node++) { pNodeProperties = m_NodeInfo.GetNodeProperties(node); if (pNodeProperties != NULL) { HSAuint64 uniqueid; if (!pNodeProperties->UniqueID) uniqueid = 0; else uniqueid = pNodeProperties->UniqueID; LOG() << "UniqueID : " << std::dec << uniqueid << " Node index: " << node << std::endl; // Checking for cpu core only if it's a cpu only node or if its KAVERI apu. if (pNodeProperties->DeviceId == 0 || FamilyIdFromNode(pNodeProperties) == FAMILY_KV) { EXPECT_GT(pNodeProperties->NumCPUCores, HSAuint32(0)) << "Node index: " << node << " No CPUs core are connected for node index"; } // If it's not a cpu only node, look for a gpu core if (pNodeProperties->DeviceId != 0) { EXPECT_GT(pNodeProperties->NumFComputeCores, HSAuint32(0)) << "Node index: " << node << "No GPUs core are connected."; // EngineId only applies to GPU, not CPU-only nodes EXPECT_GT(pNodeProperties->EngineId.ui32.uCode, 0) << "uCode version is 0"; EXPECT_GE(pNodeProperties->EngineId.ui32.Major, 7) << "Major Version is less than 7"; EXPECT_LT(pNodeProperties->EngineId.ui32.Minor, 10) << "Minor Version is greater than 9"; EXPECT_GT(pNodeProperties->uCodeEngineVersions.uCodeSDMA, 0) << "sDMA firmware version is 0"; HSAuint32 VGPRSize = (FamilyIdFromNode(pNodeProperties) == FAMILY_AR || FamilyIdFromNode(pNodeProperties) == FAMILY_AL) ? 0x80000 : 0x40000; EXPECT_EQ(pNodeProperties->VGPRSizePerCU, VGPRSize) << "VGPR Size Per CU is not correct"; EXPECT_EQ(pNodeProperties->SGPRSizePerCU, 0x4000) << "SGPR Size Per CU is not correct"; LOG() << "VGPR Size is " << pNodeProperties->VGPRSizePerCU << " SGPR Size is " << pNodeProperties->SGPRSizePerCU << std::endl; } EXPECT_GT(pNodeProperties->NumMemoryBanks, HSAuint32(0)) << "Node index: " << node << "No MemoryBanks."; EXPECT_GT(pNodeProperties->NumCaches, HSAuint32(0)) << "Node index: " << node << "No Caches."; } } TEST_END } // This test verifies failure status on hsaKmtGetNodeProperties with invalid params TEST_F(KFDTopologyTest, GetNodePropertiesInvalidParams) { TEST_START(TESTPROFILE_RUNALL) EXPECT_EQ(HSAKMT_STATUS_INVALID_PARAMETER, hsaKmtGetNodeProperties(0, NULL)); TEST_END } // This test verifies failure status on hsaKmtGetNodeProperties with invalid params TEST_F(KFDTopologyTest, GetNodePropertiesInvalidNodeNum) { TEST_START(TESTPROFILE_RUNALL) HsaNodeProperties nodeProperties; memset(&nodeProperties, 0, sizeof(nodeProperties)); EXPECT_EQ(HSAKMT_STATUS_INVALID_NODE_UNIT, hsaKmtGetNodeProperties(m_SystemProperties.NumNodes, &nodeProperties)); TEST_END } // Test that we can get memory properties successfully per node // TODO: Check validity of values returned TEST_F(KFDTopologyTest, GetNodeMemoryProperties) { TEST_START(TESTPROFILE_RUNALL) const HsaNodeProperties *pNodeProperties; for (unsigned node = 0; node < m_SystemProperties.NumNodes; node++) { pNodeProperties = m_NodeInfo.GetNodeProperties(node); if (pNodeProperties != NULL) { HsaMemoryProperties *memoryProperties = new HsaMemoryProperties[pNodeProperties->NumMemoryBanks]; EXPECT_SUCCESS(hsaKmtGetNodeMemoryProperties(node, pNodeProperties->NumMemoryBanks, memoryProperties)); delete [] memoryProperties; } } TEST_END } // Test that the GPU local memory aperture is valid. TEST_F(KFDTopologyTest, GpuvmApertureValidate) { TEST_REQUIRE_NO_ENV_CAPABILITIES(ENVCAPS_32BITLINUX); TEST_START(TESTPROFILE_RUNALL) const HsaNodeProperties *pNodeProperties; const std::vector GpuNodes = m_NodeInfo.GetNodesWithGPU(); for (unsigned i = 0; i < GpuNodes.size(); i++) { pNodeProperties = m_NodeInfo.GetNodeProperties(GpuNodes.at(i)); if (pNodeProperties != NULL) { if (!is_dgpu() && !(FamilyIdFromNode(pNodeProperties) == FAMILY_KV)) { LOG() << "Skipping test: GPUVM framebuffer heap not exposed on APU except Kaveri." << std::endl; return; } HsaMemoryProperties *memoryProperties = new HsaMemoryProperties[pNodeProperties->NumMemoryBanks]; EXPECT_SUCCESS(hsaKmtGetNodeMemoryProperties(GpuNodes.at(i), pNodeProperties->NumMemoryBanks, memoryProperties)); bool GpuVMHeapFound = false; for (unsigned int bank = 0 ; bank < pNodeProperties->NumMemoryBanks ; bank++) { // Check for either private (small-bar/APU) or public (large-bar) if ((HSA_HEAPTYPE_FRAME_BUFFER_PRIVATE == memoryProperties[bank].HeapType) || (HSA_HEAPTYPE_FRAME_BUFFER_PUBLIC == memoryProperties[bank].HeapType)) GpuVMHeapFound = true; } EXPECT_TRUE(GpuVMHeapFound); delete [] memoryProperties; } } TEST_END } // Test that we can get cache property successfully per node // TODO: Check validity of values returned TEST_F(KFDTopologyTest, GetNodeCacheProperties) { TEST_START(TESTPROFILE_RUNALL) const HsaNodeProperties *pNodeProperties; for (unsigned node = 0; node < m_SystemProperties.NumNodes; node++) { pNodeProperties = m_NodeInfo.GetNodeProperties(node); if (pNodeProperties != NULL) { HsaCacheProperties *cacheProperties = new HsaCacheProperties[pNodeProperties->NumCaches]; EXPECT_SUCCESS(hsaKmtGetNodeCacheProperties(node, pNodeProperties->CComputeIdLo, pNodeProperties->NumCaches, cacheProperties)); if (pNodeProperties->NumCPUCores > 0) { // this is a CPU node LOG() << "CPU Node " << std::dec << node << ": " << pNodeProperties->NumCaches << " caches" << std::endl; for (unsigned n = 0; n < pNodeProperties->NumCaches; n++) { LOG()<< n << " - Level " << cacheProperties[n].CacheLevel << " Type " << cacheProperties[n].CacheType.Value << " Size " << (cacheProperties[n].CacheSize >> 10) << "K " << " Associativity " << cacheProperties[n].CacheAssociativity << " LineSize " << cacheProperties[n].CacheLineSize << " LinesPerTag " << cacheProperties[n].CacheLinesPerTag << std::endl; char string[1024] = ""; char sibling[5] = ""; for (unsigned i = 0; i < 256; i++) { if (cacheProperties[n].SiblingMap[i]) { sprintf(sibling, "%d,", i); strcat(string, sibling); } } LOG() << " ProcIdLow " << cacheProperties[n].ProcessorIdLow << " SiblingMap " << string << std::endl; } } else { // this is a GPU node LOG() << "GPU Node " << std::dec << node << ": " << pNodeProperties->NumCaches << " caches" << std::endl; for (unsigned n = 0; n < pNodeProperties->NumCaches; n++) { LOG()<< n << " - Level " << cacheProperties[n].CacheLevel << " Type " << cacheProperties[n].CacheType.Value << " Size " << cacheProperties[n].CacheSize << "K " << " Associativity " << cacheProperties[n].CacheAssociativity << " LineSize " << cacheProperties[n].CacheLineSize << " LinesPerTag " << cacheProperties[n].CacheLinesPerTag << std::endl; char string[1024] = ""; char sibling[5] = ""; for (unsigned i = 0; i < 256; i++) { if (cacheProperties[n].SiblingMap[i]) { snprintf(sibling, 5, "%d,", i); strcat(string, sibling); } } LOG() << " ProcIdLow " << cacheProperties[n].ProcessorIdLow << " SiblingMap " << string << std::endl; } } delete [] cacheProperties; } } TEST_END } // Test that we can get NodeIoLink property successfully per node // TODO: Check validity of values returned // GetNodeIoLinkProperties is disabled for now, test fails due to bug in BIOS TEST_F(KFDTopologyTest, GetNodeIoLinkProperties) { TEST_START(TESTPROFILE_RUNALL) const HsaNodeProperties *pNodeProperties; int linkId; char c; LOG() << "Topology. [FromNode]--(Weight)-->[ToNode]" << std::endl; for (unsigned node = 0; node < m_SystemProperties.NumNodes; node++) { pNodeProperties = m_NodeInfo.GetNodeProperties(node); if (pNodeProperties != NULL) { HsaIoLinkProperties *IolinkProperties = new HsaIoLinkProperties[pNodeProperties->NumIOLinks]; EXPECT_SUCCESS(hsaKmtGetNodeIoLinkProperties(node, pNodeProperties->NumIOLinks, IolinkProperties)); if (pNodeProperties->NumIOLinks == 0) { // No io_links. Just print the node LOG() << "[" << node << "]" << std::endl; continue; } for (linkId = 0; linkId < pNodeProperties->NumIOLinks; linkId++) { if (linkId == 0) { // First io_link. Print Parent Node and io_link Node EXPECT_EQ(node, IolinkProperties[linkId].NodeFrom); LOG() << "[" << IolinkProperties[linkId].NodeFrom << "]--(" << IolinkProperties[linkId].Weight << ")-->" << "[" << IolinkProperties[linkId].NodeTo << "]" << std::endl; continue; } if (linkId == (pNodeProperties->NumIOLinks - 1)) c = '`'; // last node else c = '|'; LOG() << " " << c << "--(" << IolinkProperties[linkId].Weight << ")-->" << "[" << IolinkProperties[linkId].NodeTo << "]" << std::endl; } LOG() << std::endl; delete [] IolinkProperties; } } TEST_END }