| /*========================== begin_copyright_notice ============================ | |
| Copyright(c) 2021 Intel Corporation | |
| 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. | |
| ============================= end_copyright_notice ===========================*/ | |
| #include "GmmMultiAdapterULT.h" | |
| #ifndef _WIN32 | |
| #include <dlfcn.h> | |
| #endif | |
| ADAPTER_INFO * MACommonULT::pGfxAdapterInfo[MAX_NUM_ADAPTERS][MAX_COUNT_PER_ADAPTER]; | |
| PLATFORM MACommonULT::GfxPlatform[MAX_NUM_ADAPTERS][MAX_COUNT_PER_ADAPTER]; | |
| GMM_LIB_CONTEXT * MACommonULT::pLibContext[MAX_NUM_ADAPTERS][MAX_COUNT_PER_ADAPTER]; | |
| GMM_CLIENT_CONTEXT *MACommonULT::pGmmULTClientContext[MAX_NUM_ADAPTERS][MAX_COUNT_PER_ADAPTER]; | |
| PFNGMMINIT MACommonULT::pfnGmmInit[MAX_NUM_ADAPTERS][MAX_COUNT_PER_ADAPTER]; | |
| PFNGMMDESTROY MACommonULT::pfnGmmDestroy[MAX_NUM_ADAPTERS][MAX_COUNT_PER_ADAPTER]; | |
| GMM_INIT_IN_ARGS MACommonULT::InArgs[MAX_NUM_ADAPTERS][MAX_COUNT_PER_ADAPTER]; | |
| GMM_INIT_OUT_ARGS MACommonULT::OutArgs[MAX_NUM_ADAPTERS][MAX_COUNT_PER_ADAPTER]; | |
| GMM_DLL_HANDLE MACommonULT::hGmmLib[MAX_NUM_ADAPTERS][MAX_COUNT_PER_ADAPTER]; | |
| void MACommonULT::SetUpTestCase() | |
| { | |
| } | |
| void MACommonULT::TearDownTestCase() | |
| { | |
| } | |
| CTestMA::CTestMA() | |
| { | |
| } | |
| CTestMA::~CTestMA() | |
| { | |
| } | |
| void CTestMA::SetUpTestCase() | |
| { | |
| } | |
| void CTestMA::TearDownTestCase() | |
| { | |
| } | |
| void MACommonULT::LoadGmmDll(uint32_t AdapterIdx, uint32_t CountIdx) | |
| { | |
| hGmmLib[AdapterIdx][CountIdx] = dlopen(GMM_UMD_DLL, RTLD_LAZY); | |
| ASSERT_TRUE(hGmmLib[AdapterIdx][CountIdx]); | |
| *(void **)(&pfnGmmInit[AdapterIdx][CountIdx]) = dlsym(hGmmLib[AdapterIdx][CountIdx], "InitializeGmm"); | |
| *(void **)(&pfnGmmDestroy[AdapterIdx][CountIdx]) = dlsym(hGmmLib[AdapterIdx][CountIdx], "GmmAdapterDestroy"); | |
| ASSERT_TRUE(pfnGmmInit[AdapterIdx][CountIdx]); | |
| ASSERT_TRUE(pfnGmmDestroy[AdapterIdx][CountIdx]); | |
| } | |
| void MACommonULT::UnLoadGmmDll(uint32_t AdapterIdx, uint32_t CountIdx) | |
| { | |
| if(hGmmLib[AdapterIdx][CountIdx]) | |
| { | |
| dlclose(hGmmLib[AdapterIdx][CountIdx]); | |
| hGmmLib[AdapterIdx][CountIdx] = NULL; | |
| } | |
| } | |
| void MACommonULT::GmmInitModule(uint32_t AdapterIdx, uint32_t CountIdx) | |
| { | |
| GMM_STATUS Status = GMM_SUCCESS; | |
| ADAPTER_BDF AdapterBDF = GetAdapterBDF(AdapterIdx); | |
| GfxPlatform[AdapterIdx][CountIdx].eProductFamily = GetProductFamily(AdapterIdx); | |
| GfxPlatform[AdapterIdx][CountIdx].eRenderCoreFamily = GetRenderCoreFamily(AdapterIdx); | |
| if(!pGfxAdapterInfo[AdapterIdx][CountIdx]) | |
| { | |
| pGfxAdapterInfo[AdapterIdx][CountIdx] = (ADAPTER_INFO *)malloc(sizeof(ADAPTER_INFO)); | |
| if(!pGfxAdapterInfo[AdapterIdx][CountIdx]) | |
| { | |
| ASSERT_TRUE(false); | |
| return; | |
| } | |
| memset(pGfxAdapterInfo[AdapterIdx][CountIdx], 0, sizeof(ADAPTER_INFO)); | |
| pGfxAdapterInfo[AdapterIdx][CountIdx]->SkuTable.FtrTileY = 1; // Legacy TileY | |
| if(GfxPlatform[AdapterIdx][CountIdx].eRenderCoreFamily >= IGFX_GEN12_CORE) | |
| { | |
| pGfxAdapterInfo[AdapterIdx][CountIdx]->SkuTable.FtrWddm2GpuMmu = 1; | |
| pGfxAdapterInfo[AdapterIdx][CountIdx]->SkuTable.FtrUserModeTranslationTable = 1; | |
| pGfxAdapterInfo[AdapterIdx][CountIdx]->SkuTable.FtrE2ECompression = 1; | |
| pGfxAdapterInfo[AdapterIdx][CountIdx]->SkuTable.FtrLinearCCS = 1; | |
| pGfxAdapterInfo[AdapterIdx][CountIdx]->SkuTable.FtrTileY = 1; | |
| pGfxAdapterInfo[AdapterIdx][CountIdx]->SkuTable.FtrLLCBypass = 0; | |
| pGfxAdapterInfo[AdapterIdx][CountIdx]->SkuTable.FtrWddm2Svm = 0; | |
| } | |
| if(IGFX_DG1 == GfxPlatform[AdapterIdx][CountIdx].eProductFamily) | |
| { | |
| pGfxAdapterInfo[AdapterIdx][CountIdx]->SkuTable.FtrLinearCCS = 1; | |
| pGfxAdapterInfo[AdapterIdx][CountIdx]->SkuTable.FtrStandardMipTailFormat = 1; | |
| pGfxAdapterInfo[AdapterIdx][CountIdx]->SkuTable.FtrTileY = 0; | |
| pGfxAdapterInfo[AdapterIdx][CountIdx]->SkuTable.FtrLocalMemory = 1; | |
| pGfxAdapterInfo[AdapterIdx][CountIdx]->SkuTable.FtrWddm2_1_64kbPages = 1; | |
| } | |
| } | |
| InArgs[AdapterIdx][CountIdx].ClientType = GetClientType(CountIdx); | |
| InArgs[AdapterIdx][CountIdx].pGtSysInfo = &pGfxAdapterInfo[AdapterIdx][CountIdx]->SystemInfo; | |
| InArgs[AdapterIdx][CountIdx].pSkuTable = &pGfxAdapterInfo[AdapterIdx][CountIdx]->SkuTable; | |
| InArgs[AdapterIdx][CountIdx].pWaTable = &pGfxAdapterInfo[AdapterIdx][CountIdx]->WaTable; | |
| InArgs[AdapterIdx][CountIdx].Platform = GfxPlatform[AdapterIdx][CountIdx]; | |
| #if LHDM | |
| InArgs[AdapterIdx][CountIdx].stAdapterBDF = AdapterBDF; | |
| InArgs[AdapterIdx][CountIdx].DeviceRegistryPath = NULL; | |
| #else | |
| InArgs[AdapterIdx][CountIdx].FileDescriptor = AdapterBDF.Data; | |
| #endif | |
| Status = pfnGmmInit[AdapterIdx][CountIdx](&InArgs[AdapterIdx][CountIdx], &OutArgs[AdapterIdx][CountIdx]); | |
| EXPECT_EQ(Status, GMM_SUCCESS); | |
| pGmmULTClientContext[AdapterIdx][CountIdx] = OutArgs[AdapterIdx][CountIdx].pGmmClientContext; | |
| ASSERT_TRUE(pGmmULTClientContext[AdapterIdx][CountIdx]); | |
| pLibContext[AdapterIdx][CountIdx] = pGmmULTClientContext[AdapterIdx][CountIdx]->GetLibContext(); | |
| ASSERT_TRUE(pLibContext[AdapterIdx][CountIdx]); | |
| } | |
| void MACommonULT::GmmDestroyModule(uint32_t AdapterIdx, uint32_t CountIdx) | |
| { | |
| OutArgs[AdapterIdx][CountIdx].pGmmClientContext = pGmmULTClientContext[AdapterIdx][CountIdx]; | |
| pfnGmmDestroy[AdapterIdx][CountIdx](&OutArgs[AdapterIdx][CountIdx]); | |
| pGmmULTClientContext[AdapterIdx][CountIdx] = NULL; | |
| pLibContext[AdapterIdx][CountIdx] = NULL; | |
| if(pGfxAdapterInfo[AdapterIdx][CountIdx]) | |
| { | |
| free(pGfxAdapterInfo[AdapterIdx][CountIdx]); | |
| pGfxAdapterInfo[AdapterIdx][CountIdx] = NULL; | |
| } | |
| } | |
| void *Thread1(void *lpParam) | |
| { | |
| ThreadInParams *pInParams = (ThreadInParams *)(lpParam); | |
| MACommonULT::LoadGmmDll(pInParams->AdapterIdx, pInParams->CountIdx); | |
| MACommonULT::GmmInitModule(pInParams->AdapterIdx, pInParams->CountIdx); | |
| MACommonULT::GmmDestroyModule(pInParams->AdapterIdx, pInParams->CountIdx); | |
| MACommonULT::UnLoadGmmDll(pInParams->AdapterIdx, pInParams->CountIdx); | |
| pthread_exit(NULL); | |
| } | |
| #if GMM_LIB_DLL_MA | |
| /// Load multiple Adapters in the same process | |
| TEST_F(CTestMA, TestLoadMultipleAdapters) | |
| { | |
| LoadGmmDll(0, 0); | |
| LoadGmmDll(1, 0); | |
| LoadGmmDll(2, 0); | |
| GmmInitModule(2, 0); | |
| GmmInitModule(0, 0); | |
| GmmInitModule(1, 0); | |
| EXPECT_NE(pLibContext[0][0], pLibContext[1][0]); | |
| EXPECT_NE(pLibContext[2][0], pLibContext[1][0]); | |
| EXPECT_NE(pLibContext[2][0], pLibContext[0][0]); | |
| GmmDestroyModule(1, 0); | |
| GmmDestroyModule(2, 0); | |
| GmmDestroyModule(0, 0); | |
| UnLoadGmmDll(2, 0); | |
| UnLoadGmmDll(1, 0); | |
| UnLoadGmmDll(0, 0); | |
| } | |
| /// Load same Adapter multiple times in same process | |
| TEST_F(CTestMA, TestLoadAdapterMultipleTimes) | |
| { | |
| LoadGmmDll(0, 0); | |
| LoadGmmDll(0, 1); | |
| LoadGmmDll(0, 2); | |
| GmmInitModule(0, 0); | |
| GmmInitModule(0, 1); | |
| GmmInitModule(0, 2); | |
| EXPECT_EQ(pLibContext[0][0], pLibContext[0][2]); | |
| EXPECT_EQ(pLibContext[0][0], pLibContext[0][1]); | |
| GmmDestroyModule(0, 0); | |
| GmmDestroyModule(0, 1); | |
| GmmDestroyModule(0, 2); | |
| UnLoadGmmDll(0, 0); | |
| UnLoadGmmDll(0, 1); | |
| UnLoadGmmDll(0, 2); | |
| } | |
| /// Test Init-Destroy multiple times before Unloading DLL, on Same Adapter | |
| TEST_F(CTestMA, TestInitDestroyMultipleTimesOnSameAdapter) | |
| { | |
| uint32_t i = 0; | |
| LoadGmmDll(0, 0); | |
| LoadGmmDll(0, 1); | |
| LoadGmmDll(0, 2); | |
| for(i = 0; i < 3; i++) | |
| { | |
| GmmInitModule(0, 0); | |
| GmmInitModule(0, 1); | |
| GmmInitModule(0, 2); | |
| EXPECT_EQ(pLibContext[0][0], pLibContext[0][2]); | |
| EXPECT_EQ(pLibContext[0][0], pLibContext[0][1]); | |
| GmmDestroyModule(0, 0); | |
| GmmDestroyModule(0, 1); | |
| GmmDestroyModule(0, 2); | |
| } | |
| UnLoadGmmDll(0, 0); | |
| UnLoadGmmDll(0, 1); | |
| UnLoadGmmDll(0, 2); | |
| } | |
| /// Test Init-Destroy multiple times before Unloading DLL, on Multiple Adapters | |
| TEST_F(CTestMA, TestInitDestroyMultipleTimesOnMultiAdapter) | |
| { | |
| uint32_t i = 0; | |
| LoadGmmDll(0, 0); | |
| LoadGmmDll(1, 0); | |
| LoadGmmDll(2, 0); | |
| for(i = 0; i < 3; i++) | |
| { | |
| GmmInitModule(0, 0); | |
| GmmInitModule(1, 0); | |
| GmmInitModule(2, 0); | |
| //EXPECT_NE for Multi-Adapter support is added to Linux | |
| EXPECT_NE(pLibContext[0][0], pLibContext[1][0]); | |
| EXPECT_NE(pLibContext[2][0], pLibContext[1][0]); | |
| EXPECT_NE(pLibContext[2][0], pLibContext[0][0]); | |
| GmmDestroyModule(2, 0); | |
| GmmDestroyModule(1, 0); | |
| GmmDestroyModule(0, 0); | |
| } | |
| UnLoadGmmDll(2, 0); | |
| UnLoadGmmDll(1, 0); | |
| UnLoadGmmDll(0, 0); | |
| } | |
| // Load Multiple Adapters on multiple threads in same process | |
| TEST_F(CTestMA, TestMTLoadMultipleAdapters) | |
| { | |
| ThreadInParams InParams[3]; | |
| uint32_t i = 0; | |
| InParams[0].AdapterIdx = 0; | |
| InParams[0].CountIdx = 0; | |
| InParams[1].AdapterIdx = 1; | |
| InParams[1].CountIdx = 0; | |
| InParams[2].AdapterIdx = 2; | |
| InParams[2].CountIdx = 0; | |
| int Status; /* return value */ | |
| pthread_t thread_id[3]; /* thread's ID (just an integer) */ | |
| for(i = 0; i < 3; i++) | |
| { | |
| Status = pthread_create(&thread_id[i], NULL, Thread1, (void *)&InParams[i]); | |
| ASSERT_TRUE((!Status)); | |
| } | |
| /* wait for threads to terminate */ | |
| for(i = 0; i < 3; i++) | |
| { | |
| Status = pthread_join(thread_id[i], NULL); | |
| ASSERT_TRUE((!Status)); | |
| } | |
| } | |
| // Load a single Adapter on multiple threads in same process | |
| TEST_F(CTestMA, TestMTLoadAdaptersMultipleTimes) | |
| { | |
| ThreadInParams InParams[3]; | |
| uint32_t i = 0; | |
| InParams[0].AdapterIdx = 0; | |
| InParams[0].CountIdx = 0; | |
| InParams[1].AdapterIdx = 0; | |
| InParams[1].CountIdx = 1; | |
| InParams[2].AdapterIdx = 0; | |
| InParams[2].CountIdx = 2; | |
| int Status; /* return value */ | |
| pthread_t thread_id[3]; /* thread's ID (just an integer) */ | |
| for(i = 0; i < 3; i++) | |
| { | |
| Status = pthread_create(&thread_id[i], NULL, Thread1, (void *)&InParams[i]); | |
| ASSERT_TRUE((!Status)); | |
| } | |
| /* wait for threads to terminate */ | |
| for(i = 0; i < 3; i++) | |
| { | |
| Status = pthread_join(thread_id[i], NULL); | |
| ASSERT_TRUE((!Status)); | |
| } | |
| } | |
| // Load Multiple Adapters, multiple times on multiple threads in same process | |
| TEST_F(CTestMA, TestMTLoadMultipleAdaptersMultipleTimes) | |
| { | |
| ThreadInParams InParams[9]; | |
| uint32_t i = 0; | |
| InParams[0].AdapterIdx = 0; | |
| InParams[0].CountIdx = 0; | |
| InParams[1].AdapterIdx = 1; | |
| InParams[1].CountIdx = 0; | |
| InParams[2].AdapterIdx = 2; | |
| InParams[2].CountIdx = 0; | |
| InParams[3].AdapterIdx = 0; | |
| InParams[3].CountIdx = 1; | |
| InParams[4].AdapterIdx = 1; | |
| InParams[4].CountIdx = 1; | |
| InParams[5].AdapterIdx = 2; | |
| InParams[5].CountIdx = 1; | |
| InParams[6].AdapterIdx = 0; | |
| InParams[6].CountIdx = 2; | |
| InParams[7].AdapterIdx = 1; | |
| InParams[7].CountIdx = 2; | |
| InParams[8].AdapterIdx = 2; | |
| InParams[8].CountIdx = 2; | |
| int Status; /* return value */ | |
| pthread_t thread_id[9]; /* thread's ID (just an integer) */ | |
| for(i = 0; i < 9; i++) | |
| { | |
| Status = pthread_create(&thread_id[i], NULL, Thread1, (void *)&InParams[i]); | |
| ASSERT_TRUE((!Status)); | |
| } | |
| /* wait for threads to terminate */ | |
| for(i = 0; i < 9; i++) | |
| { | |
| Status = pthread_join(thread_id[i], NULL); | |
| ASSERT_TRUE((!Status)); | |
| } | |
| } | |
| #endif // GMM_LIB_DLL_MA | |