1 /*
2  * Copyright (C) 2014-2018 Advanced Micro Devices, Inc. All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included in
12  * all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20  * OTHER DEALINGS IN THE SOFTWARE.
21  *
22  */
23 
24 #include "KFDTopologyTest.hpp"
25 #include <vector>
26 #include <string>
27 
28 // @todo complete topology test according to whats in: hsathk\source\windows\kmt_topology.cpp
29 
30 const unsigned long long KFDTopologyTest::c_4Gigabyte = (1ull << 32) - 1;
31 const unsigned long long KFDTopologyTest::c_40BitAddressSpace = (1ull << 40);
32 
TEST_F(KFDTopologyTest,BasicTest)33 TEST_F(KFDTopologyTest , BasicTest) {
34     TEST_START(TESTPROFILE_RUNALL)
35 
36     const HsaNodeProperties *pNodeProperties;
37 
38     // goes over all nodes in the sytem properties and check the basic info received
39     for (unsigned node = 0; node < m_SystemProperties.NumNodes; node++) {
40         pNodeProperties = m_NodeInfo.GetNodeProperties(node);
41         if (pNodeProperties != NULL) {
42             // checking for cpu core only if it's a cpu only node or if its KAVERY apu.
43             if (pNodeProperties->DeviceId == 0 || FamilyIdFromNode(pNodeProperties) == FAMILY_KV) {
44                 EXPECT_GT(pNodeProperties->NumCPUCores, HSAuint32(0)) << "Node index: " << node << " No CPUs core are connected for node index";
45             }
46 
47             // if it's not a cpu only node, look for a gpu core
48             if (pNodeProperties->DeviceId != 0) {
49                 EXPECT_GT(pNodeProperties->NumFComputeCores, HSAuint32(0)) << "Node index: " << node << "No GPUs core are connected.";
50                 // EngineId only applies to GPU, not CPU-only nodes
51                 EXPECT_GT(pNodeProperties->EngineId.ui32.uCode, 0) << "uCode version is 0";
52                 EXPECT_GE(pNodeProperties->EngineId.ui32.Major, 7) << "Major Version is less than 7";
53                 EXPECT_LT(pNodeProperties->EngineId.ui32.Minor, 10) << "Minor Version is greater than 9";
54                 EXPECT_LT(pNodeProperties->EngineId.ui32.Stepping, 10) << "Stepping is greater than 9";
55                 EXPECT_GT(pNodeProperties->uCodeEngineVersions.uCodeSDMA, 0) << "sDMA firmware version is 0";
56             }
57             EXPECT_GT(pNodeProperties->NumMemoryBanks, HSAuint32(0)) << "Node index: " << node << "No MemoryBanks.";
58             EXPECT_GT(pNodeProperties->NumCaches, HSAuint32(0)) << "Node index: " << node << "No Caches.";
59         }
60     }
61 
62     TEST_END
63 }
64 
65 // this test verify failure status on hsaKmtGetNodeProperties with invalid params
TEST_F(KFDTopologyTest,GetNodePropertiesInvalidParams)66 TEST_F(KFDTopologyTest, GetNodePropertiesInvalidParams) {
67     TEST_START(TESTPROFILE_RUNALL)
68 
69     EXPECT_EQ(HSAKMT_STATUS_INVALID_PARAMETER, hsaKmtGetNodeProperties(0, NULL));
70 
71     TEST_END
72 }
73 
74 // this test verify failure status on hsaKmtGetNodeProperties with invalid params
TEST_F(KFDTopologyTest,GetNodePropertiesInvalidNodeNum)75 TEST_F(KFDTopologyTest, GetNodePropertiesInvalidNodeNum) {
76     TEST_START(TESTPROFILE_RUNALL)
77 
78     HsaNodeProperties nodeProperties;
79     memset(&nodeProperties, 0, sizeof(nodeProperties));
80     EXPECT_EQ(HSAKMT_STATUS_INVALID_PARAMETER, hsaKmtGetNodeProperties(m_SystemProperties.NumNodes, &nodeProperties));
81 
82     TEST_END
83 }
84 
85 // test that we can get memory property successfully per node
86 // @todo check validity of values returned
TEST_F(KFDTopologyTest,GetNodeMemoryProperties)87 TEST_F(KFDTopologyTest, GetNodeMemoryProperties) {
88     TEST_START(TESTPROFILE_RUNALL)
89     const HsaNodeProperties *pNodeProperties;
90 
91     for (unsigned node = 0; node < m_SystemProperties.NumNodes; node++) {
92         pNodeProperties = m_NodeInfo.GetNodeProperties(node);
93 
94         if (pNodeProperties != NULL) {
95             HsaMemoryProperties *memoryProperties = new HsaMemoryProperties[pNodeProperties->NumMemoryBanks];
96             EXPECT_SUCCESS(hsaKmtGetNodeMemoryProperties(node, pNodeProperties->NumMemoryBanks, memoryProperties));
97             delete [] memoryProperties;
98         }
99     }
100 
101     TEST_END
102 }
103 
104 
105 // test the GPU local memory aperture is valid.
TEST_F(KFDTopologyTest,GpuvmApertureValidate)106 TEST_F(KFDTopologyTest, GpuvmApertureValidate) {
107     TEST_REQUIRE_NO_ENV_CAPABILITIES(ENVCAPS_32BITLINUX);
108 
109     TEST_START(TESTPROFILE_RUNALL)
110     const HsaNodeProperties *pNodeProperties;
111     const std::vector<int> GpuNodes = m_NodeInfo.GetNodesWithGPU();
112 
113     for (unsigned i = 0; i < GpuNodes.size(); i++) {
114         pNodeProperties = m_NodeInfo.GetNodeProperties(GpuNodes.at(i));
115         if (pNodeProperties != NULL) {
116             if (!is_dgpu() && !(FamilyIdFromNode(pNodeProperties) == FAMILY_KV)) {
117                 LOG() << "Skipping test: GPUVM framebuffer heap not exposed on APU except Kaveri" << std::endl;
118                 return;
119             }
120             HsaMemoryProperties *memoryProperties =  new HsaMemoryProperties[pNodeProperties->NumMemoryBanks];
121             EXPECT_SUCCESS(hsaKmtGetNodeMemoryProperties(GpuNodes.at(i), pNodeProperties->NumMemoryBanks, memoryProperties));
122             bool GpuVMHeapFound = false;
123             for (unsigned int bank = 0 ; bank  < pNodeProperties->NumMemoryBanks ; bank++) {
124                 // Check for either private (small-bar/APU) or public (large-bar)
125                 if ((HSA_HEAPTYPE_FRAME_BUFFER_PRIVATE == memoryProperties[bank].HeapType) ||
126                      (HSA_HEAPTYPE_FRAME_BUFFER_PUBLIC == memoryProperties[bank].HeapType))
127                     GpuVMHeapFound = true;
128             }
129             EXPECT_TRUE(GpuVMHeapFound);
130             delete [] memoryProperties;
131         }
132     }
133 
134     TEST_END
135 }
136 
137 // test that we can get cache property successfully per node
138 // @todo check validity of values returned
TEST_F(KFDTopologyTest,GetNodeCacheProperties)139 TEST_F(KFDTopologyTest, GetNodeCacheProperties) {
140     TEST_START(TESTPROFILE_RUNALL)
141 
142     const HsaNodeProperties *pNodeProperties;
143 
144     for (unsigned node = 0; node < m_SystemProperties.NumNodes; node++) {
145         pNodeProperties = m_NodeInfo.GetNodeProperties(node);
146         if (pNodeProperties != NULL) {
147             HsaCacheProperties *cacheProperties = new HsaCacheProperties[pNodeProperties->NumCaches];
148             EXPECT_SUCCESS(hsaKmtGetNodeCacheProperties(node, pNodeProperties->CComputeIdLo, pNodeProperties->NumCaches, cacheProperties));
149             if (pNodeProperties->NumCPUCores > 0) {  // this is a CPU node
150                 LOG() << "CPU Node " << std::dec << node << ": " << pNodeProperties->NumCaches << " caches" << std::endl;
151                 for (unsigned n = 0; n < pNodeProperties->NumCaches; n++) {
152                     LOG()<< n << " - Level " << cacheProperties[n].CacheLevel <<
153                     " Type " << cacheProperties[n].CacheType.Value <<
154                     " Size " << (cacheProperties[n].CacheSize >> 10) << "K " <<
155                     " Associativity " << cacheProperties[n].CacheAssociativity <<
156                     " LineSize " << cacheProperties[n].CacheLineSize <<
157                     " LinesPerTag " << cacheProperties[n].CacheLinesPerTag << std::endl;
158                     char string[1024] = "";
159                     char sibling[5] = "";
160                     for (unsigned i = 0; i < 256; i++) {
161                         if (cacheProperties[n].SiblingMap[i]) {
162                             sprintf(sibling, "%d,", i);
163                             strcat(string, sibling);
164                         }
165                     }
166                     LOG() << "     ProcIdLow " << cacheProperties[n].ProcessorIdLow <<
167                     " SiblingMap " << string << std::endl;
168                 }
169             }
170             delete [] cacheProperties;
171         }
172     }
173 
174     TEST_END
175 }
176 
177 // test that we can get NodeIoLink property successfully per node
178 // @todo check validity of values returned
179 // GetNodeIoLinkProperties is disabled for now, test fails due to bug in BIOS
TEST_F(KFDTopologyTest,GetNodeIoLinkProperties)180 TEST_F(KFDTopologyTest, GetNodeIoLinkProperties) {
181     TEST_START(TESTPROFILE_RUNALL)
182     const HsaNodeProperties *pNodeProperties;
183     int linkId;
184     char c;
185 
186     LOG() << "Topology. [FromNode]--(Weight)-->[ToNode]" << std::endl;
187 
188     for (unsigned node = 0; node < m_SystemProperties.NumNodes; node++) {
189         pNodeProperties = m_NodeInfo.GetNodeProperties(node);
190 
191         if (pNodeProperties != NULL) {
192             HsaIoLinkProperties  *IolinkProperties =  new HsaIoLinkProperties[pNodeProperties->NumIOLinks];
193             EXPECT_SUCCESS(hsaKmtGetNodeIoLinkProperties(node, pNodeProperties->NumIOLinks, IolinkProperties));
194             if (pNodeProperties->NumIOLinks == 0) {
195                 // No io_links. Just Print the node
196                 LOG() << "[" << node << "]" << std::endl;
197                 continue;
198             }
199 
200             for (linkId = 0; linkId < pNodeProperties->NumIOLinks; linkId++) {
201                 if (linkId == 0) {
202                     // First io_link. Print Parent Node and io_link Node
203                     LOG() << "[" << node << "]--(" << IolinkProperties[linkId].Weight << ")-->" <<
204                         "[" << IolinkProperties[linkId].NodeTo << "]" << std::endl;
205                     continue;
206                 }
207                 if (linkId == (pNodeProperties->NumIOLinks - 1))
208                     c = '`';  // last node
209                 else
210                     c = '|';
211                 LOG() << "  " << c << "--(" << IolinkProperties[linkId].Weight << ")-->" <<
212                     "[" << IolinkProperties[linkId].NodeTo << "]" << std::endl;
213             }
214             LOG() << std::endl;
215             delete [] IolinkProperties;
216         }
217     }
218 
219     TEST_END
220 }
221