1 /*==============================================================================
2 Copyright(c) 2017 Intel Corporation
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
12 in all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR 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 #include "Internal/Common/GmmLibInc.h"
24 
25 #if(!defined(__GMM_KMD__) && !GMM_LIB_DLL_MA)
26 int32_t GmmLib::Context::RefCount = 0;
27 #endif
28 
29 #ifdef GMM_LIB_DLL
30 
31 // Create Mutex Object used for syncronization of ProcessSingleton Context
32 #if !GMM_LIB_DLL_MA
33 #ifdef _WIN32
34 GMM_MUTEX_HANDLE GmmLib::Context::SingletonContextSyncMutex = ::CreateMutex(NULL, FALSE, NULL);
35 #else
36 GMM_MUTEX_HANDLE      GmmLib::Context::SingletonContextSyncMutex = PTHREAD_MUTEX_INITIALIZER;
37 #endif // _WIN32
38 #endif
39 
40 /////////////////////////////////////////////////////////////////////////////////////
41 /// GMM lib DLL Multi Adapter Functions
42 /////////////////////////////////////////////////////////////////////////////////////
43 GMM_MA_LIB_CONTEXT *pGmmMALibContext = NULL;
44 
45 /////////////////////////////////////////////////////////////////////////////////////
46 /// Function to create GmmMultiAdapterContext Object
47 /// Since Linux doesnt have DLL Main equivalent, adding __attribute__((constructor))
48 /// for this GmmCreateMultiAdapterContext()
49 /////////////////////////////////////////////////////////////////////////////////////
GmmCreateMultiAdapterContext()50 extern "C" GMM_LIB_API_CONSTRUCTOR void GmmCreateMultiAdapterContext()
51 {
52     if(!pGmmMALibContext)
53     {
54         pGmmMALibContext = new GMM_MA_LIB_CONTEXT();
55     }
56 }
57 
58 /////////////////////////////////////////////////////////////////////////////////////
59 /// Function to Destroy GmmMultiAdapterContext Object
60 /// Since Linux doesnt have DLL Main equivalent, adding __attribute__((destructor))
61 /// for this GmmDestroyMultiAdapterContext()
62 /////////////////////////////////////////////////////////////////////////////////////
GmmDestroyMultiAdapterContext()63 extern "C" GMM_LIB_API_DESTRUCTOR void GmmDestroyMultiAdapterContext()
64 {
65     if(pGmmMALibContext)
66     {
67         // Before destroying GmmMultiAdapterContext, check if all the Adapters have
68         // their GmmLibContext destroyed.
69         if(!pGmmMALibContext->GetNumAdapters())
70         {
71             delete pGmmMALibContext;
72             pGmmMALibContext = NULL;
73         }
74     }
75 }
76 
77 /////////////////////////////////////////////////////////////////////////////////////
78 /// GMM lib DLL function for creating Singleton Context (GmmLib::Context)
79 /// object which shall be process singleton across all UMD clients within a process.
80 /// @see        Class GmmLib::Context
81 ///
82 /// @param[in]  Platform: platform variable. Includes product family (Haswell, Cherryview,
83 ///                       Broxton) with related render and display core revision (GEN3,
84 //                        ..., GEN10)
85 /// @param[in]  pSkuTable: Pointer to the sku feature table. Set of capabilities to
86 ///                        allow code paths to be feature based and GEN agnostic.
87 /// @param[in]  pWaTable:  Pointer to the work around table. A set of anti-features,
88 ///                        often in early/prototype silicon that require work-arounds
89 ///                        until they are resolved to allow code paths to be GEN agnostic.
90 /// @param[in]  pGtSysInfo: Pointer to the GT system info. Contains various GT System
91 ///                        Information such as EU counts, Thread Counts, Cache Sizes etc.
92 /// @param[in]  sBDF: Adapter's BDF info for which SingletonContext has to be created
93 /// @return     GMM_SUCCESS if Context is created, GMM_ERROR otherwise
94 /////////////////////////////////////////////////////////////////////////////////////
95 #ifdef _WIN32
GmmCreateLibContext(const PLATFORM Platform,const SKU_FEATURE_TABLE * pSkuTable,const WA_TABLE * pWaTable,const GT_SYSTEM_INFO * pGtSysInfo,ADAPTER_BDF sBdf)96 extern "C" GMM_STATUS GMM_STDCALL GmmCreateLibContext(const PLATFORM           Platform,
97                                                       const SKU_FEATURE_TABLE *pSkuTable,
98                                                       const WA_TABLE *         pWaTable,
99                                                       const GT_SYSTEM_INFO *   pGtSysInfo,
100                                                       ADAPTER_BDF              sBdf)
101 #else
102 extern "C" GMM_STATUS GMM_STDCALL GmmCreateLibContext(const PLATFORM Platform,
103                                                       const void *   pSkuTable,
104                                                       const void *   pWaTable,
105                                                       const void *   pGtSysInfo,
106                                                       ADAPTER_BDF    sBdf)
107 #endif
108 {
109     __GMM_ASSERTPTR(pSkuTable, GMM_ERROR);
110     __GMM_ASSERTPTR(pWaTable, GMM_ERROR);
111     __GMM_ASSERTPTR(pGtSysInfo, GMM_ERROR);
112 
113     GMM_STATUS         Status = GMM_SUCCESS;
114     SKU_FEATURE_TABLE *skuTable;
115     WA_TABLE *         waTable;
116     GT_SYSTEM_INFO *   sysInfo;
117     GMM_LIB_CONTEXT *  pGmmLibContext = NULL;
118 
119     skuTable = (SKU_FEATURE_TABLE *)pSkuTable;
120     waTable  = (WA_TABLE *)pWaTable;
121     sysInfo  = (GT_SYSTEM_INFO *)pGtSysInfo;
122 
123     // If pGmmMALibContext object is NULL, return error as DLL load would have failed
124     if(!pGmmMALibContext)
125     {
126         return GMM_ERROR;
127     }
128 
129     GMM_STATUS SyncLockStatus = pGmmMALibContext->LockMAContextSyncMutex();
130     if(SyncLockStatus == GMM_SUCCESS)
131     {
132         Status = pGmmMALibContext->IntializeAdapterInfo(sBdf);
133         if(GMM_SUCCESS != Status)
134         {
135             pGmmMALibContext->UnLockMAContextSyncMutex();
136             return GMM_ERROR;
137         }
138 
139         int32_t ContextRefCount = pGmmMALibContext->IncrementRefCount(sBdf);
140         if(ContextRefCount)
141         {
142             pGmmMALibContext->UnLockMAContextSyncMutex();
143             return GMM_SUCCESS;
144         }
145 
146         pGmmLibContext = new GMM_LIB_CONTEXT();
147         if(!pGmmLibContext)
148         {
149             pGmmMALibContext->DecrementRefCount(sBdf);
150             pGmmMALibContext->ReleaseAdapterInfo(sBdf);
151             pGmmMALibContext->UnLockMAContextSyncMutex();
152             return GMM_ERROR;
153         }
154 
155         Status = (pGmmLibContext->InitContext(Platform, skuTable, waTable, sysInfo, GMM_KMD_VISTA));
156 
157 #if LHDM
158         // Intialize SingletonContext Data.
159         // ProcessHeap creation requires size and GfxAddress parameters. These parameters are contants
160         // and are given by GMM lib internally by PageTableMgr. Hence pHeapObj should be created here at the
161         // time of SingletonContext creation. But untill all UMD clients have moved to GMM DLL, then we will
162         // create this here.
163         pGmmLibContext->pHeapObj           = NULL;
164         pGmmLibContext->ProcessHeapCounter = 0;
165 
166         // ProcessVA Gfx partition should be created here using VirtualAlloc at the time of SingletonContext
167         // creation. But untill all UMD clients have moved to GMM DLL, then we will
168         // create this here.
169         pGmmLibContext->ProcessVA        = {0};
170         pGmmLibContext->ProcessVACounter = 0;
171 
172         pGmmLibContext->IsSVMReserved = 0;
173 #endif
174 
175         pGmmLibContext->sBdf = sBdf;
176 
177         pGmmMALibContext->SetAdapterLibContext(sBdf, pGmmLibContext);
178 
179         pGmmMALibContext->UnLockMAContextSyncMutex();
180 
181         return Status;
182     }
183     else
184     {
185         return GMM_ERROR;
186     }
187 }
188 
189 /////////////////////////////////////////////////////////////////////////////////////
190 /// GMM lib DLL function for deleting the Singleton Context.
191 /// Reference Count will be decremented and once the reference count reaches 0,
192 /// Singleton Context will be freeed in memory
193 ///
194 /// @param[in] sbdf: Adapter's BDF info that needs its SingletonContext to be freed
195 /////////////////////////////////////////////////////////////////////////////////////
GmmLibContextFree(ADAPTER_BDF sBdf)196 extern "C" void GMM_STDCALL GmmLibContextFree(ADAPTER_BDF sBdf)
197 {
198     if(pGmmMALibContext)
199     {
200         __GMM_ASSERTPTR(pGmmMALibContext->GetAdapterLibContext(sBdf), VOIDRETURN);
201 
202         GMM_STATUS SyncLockStatus = pGmmMALibContext->LockMAContextSyncMutex();
203         if(SyncLockStatus == GMM_SUCCESS)
204         {
205             int32_t ContextRefCount = pGmmMALibContext->DecrementRefCount(sBdf);
206             if(!ContextRefCount && pGmmMALibContext->GetAdapterLibContext(sBdf))
207             {
208                 pGmmMALibContext->GetAdapterLibContext(sBdf)->DestroyContext();
209                 delete pGmmMALibContext->GetAdapterLibContext(sBdf);
210                 pGmmMALibContext->ReleaseAdapterInfo(sBdf);
211             }
212 
213             pGmmMALibContext->UnLockMAContextSyncMutex();
214         }
215     }
216 }
217 
218 
219 /////////////////////////////////////////////////////////////////////////////////////
220 /// Constructor to zero initialize the GmmLib::GmmMultiAdapterContext object and create
221 /// GmmMultiAdapterContext class object
222 /////////////////////////////////////////////////////////////////////////////////////
GmmMultiAdapterContext()223 GmmLib::GmmMultiAdapterContext::GmmMultiAdapterContext()
224 {
225     uint32_t i = 0;
226 
227     memset(AdapterInfo, 0, sizeof(AdapterInfo));
228     NumAdapters = 0;
229     pCpuReserveBase = NULL;
230     CpuReserveSize  = 0;
231 
232 
233     for(i = 0; i < MAX_NUM_ADAPTERS; i++)
234     {
235         // Initiaze bdf to 0xFF, as {0,0,0} can be valid bdf
236         AdapterInfo[i].sBdf = {0xFF, 0xFF, 0xFF, 0};
237 #ifdef _WIN32
238         AdapterInfo[i].SyncMutex = ::CreateMutex(NULL, FALSE, NULL);
239 #else
240         AdapterInfo[i].SyncMutex = PTHREAD_MUTEX_INITIALIZER;
241 #endif // _WIN32
242     }
243 
244 #ifdef _WIN32
245     MAContextSyncMutex = ::CreateMutex(NULL, FALSE, NULL);
246 #else
247     MAContextSyncMutex           = PTHREAD_MUTEX_INITIALIZER;
248 #endif // _WIN32
249 }
250 
251 /////////////////////////////////////////////////////////////////////////////////////
252 /// Destructor to free  GmmLib::GmmMultiAdapterContext object memory
253 /////////////////////////////////////////////////////////////////////////////////////
~GmmMultiAdapterContext()254 GmmLib::GmmMultiAdapterContext::~GmmMultiAdapterContext()
255 {
256     uint32_t i = 0;
257 
258     for(i = 0; i < MAX_NUM_ADAPTERS; i++)
259     {
260 #ifdef _WIN32
261         if(AdapterInfo[i].SyncMutex)
262         {
263             ::CloseHandle(AdapterInfo[i].SyncMutex);
264             AdapterInfo[i].SyncMutex = NULL;
265         }
266 #else
267         pthread_mutex_destroy(&AdapterInfo[i].SyncMutex);
268 #endif // _WIN32
269     }
270 
271 #ifdef _WIN32
272     if(MAContextSyncMutex)
273     {
274         ::CloseHandle(MAContextSyncMutex);
275         MAContextSyncMutex = NULL;
276     }
277 #else
278     pthread_mutex_destroy(&MAContextSyncMutex);
279 #endif // _WIN32
280 }
281 
282 /////////////////////////////////////////////////////////////////////////////////////
283 /// Member function of GmmMultiAdapterContext class for initializing Adapter details
284 ///
285 /// @param[in]  sBdf       : Adpater Bus, Device and Function details
286 /// @return     GMM_STATUS
287 /////////////////////////////////////////////////////////////////////////////////////
IntializeAdapterInfo(ADAPTER_BDF sBdf)288 GMM_STATUS GMM_STDCALL GmmLib::GmmMultiAdapterContext::IntializeAdapterInfo(ADAPTER_BDF sBdf)
289 {
290     GMM_STATUS Status = GMM_SUCCESS;
291     uint32_t   i      = 0;
292 
293     for(i = 0; i < MAX_NUM_ADAPTERS; i++)
294     {
295         if((sBdf.Bus == AdapterInfo[i].sBdf.Bus) &&
296            (sBdf.Device == AdapterInfo[i].sBdf.Device) &&
297            (sBdf.Function == AdapterInfo[i].sBdf.Function))
298         {
299             break;
300         }
301     }
302 
303     if(i < MAX_NUM_ADAPTERS)
304     {
305         // Already intialized, do nothing
306     }
307     else
308     {
309         // error check if NumAdapters is greater than MAX_NUM_ADAPTERS, then fail this call
310         if(NumAdapters == MAX_NUM_ADAPTERS)
311         {
312             Status = GMM_ERROR;
313         }
314         else
315         {
316             // Search for a free slot in the AdapterInfo Array to add this BDF
317             ADAPTER_BDF FreeSlotBdf = {0xFF, 0xFF, 0xFF, 0};
318             uint32_t    AdapterIdx  = GetAdapterIndex(FreeSlotBdf);
319 
320             AdapterInfo[AdapterIdx].sBdf.Bus      = sBdf.Bus;
321             AdapterInfo[AdapterIdx].sBdf.Device   = sBdf.Device;
322             AdapterInfo[AdapterIdx].sBdf.Function = sBdf.Function;
323             NumAdapters++;
324         }
325     }
326 
327     return Status;
328 }
329 
330 /////////////////////////////////////////////////////////////////////////////////////
331 /// Member function of GmmMultiAdapterContext class for releasing Adapter details
332 ///
333 /// @param[in]  sBdf       : Adpater Bus, Device and Fucntion details
334 /// @return     GMM_STATUS
335 /////////////////////////////////////////////////////////////////////////////////////
ReleaseAdapterInfo(ADAPTER_BDF sBdf)336 void GMM_STDCALL GmmLib::GmmMultiAdapterContext::ReleaseAdapterInfo(ADAPTER_BDF sBdf)
337 {
338     uint32_t AdapterIdx = GetAdapterIndex(sBdf);
339     if(AdapterIdx < MAX_NUM_ADAPTERS)
340     {
341         AdapterInfo[AdapterIdx].sBdf           = {0xFF, 0xFF, 0xFF, 0};
342         AdapterInfo[AdapterIdx].pGmmLibContext = NULL;
343         NumAdapters--;
344     }
345 }
346 
347 /////////////////////////////////////////////////////////////////////////////////////
348 /// Member function of GmmMultiAdapterContext class for returning the AdapterIdx
349 ///
350 /// @param[in]  sBdf       : Adpater Bus, Device and Fucntion details
351 /// @return     Adpater Idx corresponding the given BDF.
352 /////////////////////////////////////////////////////////////////////////////////////
GetAdapterIndex(ADAPTER_BDF sBdf)353 uint32_t GMM_STDCALL GmmLib::GmmMultiAdapterContext::GetAdapterIndex(ADAPTER_BDF sBdf)
354 {
355     uint32_t AdapterIdx = 0;
356     for(AdapterIdx = 0; AdapterIdx < MAX_NUM_ADAPTERS; AdapterIdx++)
357     {
358         if((sBdf.Bus == AdapterInfo[AdapterIdx].sBdf.Bus) &&
359            (sBdf.Device == AdapterInfo[AdapterIdx].sBdf.Device) &&
360            (sBdf.Function == AdapterInfo[AdapterIdx].sBdf.Function))
361         {
362             break;
363         }
364     }
365 
366     return AdapterIdx;
367 }
368 
369 ///////////////////////////////////////////////////////////////////////////////////////
370 /// Member function of GmmMultiAdapterContext class for returning the GmmLibContext
371 ///
372 /// @param[in]  sBdf       : Adpater Bus, Device and Fucntion details
373 /// @return     GmmLibContext corresponding the given BDF.
374 //////////////////////////////////////////////////////////////////////////////////////
GetAdapterLibContext(ADAPTER_BDF sBdf)375 GmmLib::Context *GMM_STDCALL GmmLib::GmmMultiAdapterContext::GetAdapterLibContext(ADAPTER_BDF sBdf)
376 {
377     uint32_t AdapterIdx = GetAdapterIndex(sBdf);
378     if(AdapterIdx < MAX_NUM_ADAPTERS)
379     {
380         return AdapterInfo[AdapterIdx].pGmmLibContext;
381     }
382     else
383     {
384         return NULL;
385     }
386 }
387 
388 /////////////////////////////////////////////////////////////////////////////////////
389 /// Member function of GmmMultiAdapterContext class for setting the GmmLibContext
390 ///
391 /// @param[in]  sBdf       : Adpater Bus, Device and Fucntion details
392 /// @param[in]  pointer to GmmLibCOntext corresponding to the given BDF
393 /// @return     void.
394 /////////////////////////////////////////////////////////////////////////////////////
SetAdapterLibContext(ADAPTER_BDF sBdf,GmmLib::Context * pGmmLibContext)395 void GMM_STDCALL GmmLib::GmmMultiAdapterContext::SetAdapterLibContext(ADAPTER_BDF sBdf, GmmLib::Context *pGmmLibContext)
396 {
397     uint32_t AdapterIdx = GetAdapterIndex(sBdf);
398     if(AdapterIdx < MAX_NUM_ADAPTERS)
399     {
400         AdapterInfo[AdapterIdx].pGmmLibContext = pGmmLibContext;
401     }
402 }
403 
404 /////////////////////////////////////////////////////////////////////////////////////
405 /// Member function of GmmMultiAdapterContext class for returning the NumAdapters
406 /// that are intialized within a process
407 ///
408 /// @return     Number of Adpaters that are opened and initialized within a process.
409 /////////////////////////////////////////////////////////////////////////////////////
GetNumAdapters()410 uint32_t GMM_STDCALL GmmLib::GmmMultiAdapterContext::GetNumAdapters()
411 {
412     return NumAdapters;
413 }
414 
415 #ifdef _WIN32
416 /////////////////////////////////////////////////////////////////////////////////////
417 /// Member function of GmmMultiAdapterContext class for Locking MultiAdapter Mutex
418 /// SyncMutex to protect access of GmmMultiAdpaterContext object
419 ///
420 /// @return     GMM_STATUS.
421 /////////////////////////////////////////////////////////////////////////////////////
LockMAContextSyncMutex()422 GMM_STATUS GMM_STDCALL GmmLib::GmmMultiAdapterContext::LockMAContextSyncMutex()
423 {
424     if(MAContextSyncMutex)
425     {
426         while(WAIT_OBJECT_0 != ::WaitForSingleObject(MAContextSyncMutex, INFINITE))
427             ;
428         return GMM_SUCCESS;
429     }
430     else
431     {
432         return GMM_ERROR;
433     }
434 }
435 
436 /////////////////////////////////////////////////////////////////////////////////////
437 /// Member function of GmmMultiAdapterContext class for UnLocking MultiAdapter Mutex
438 /// SyncMutex to protect access of GmmMultiAdpaterContext
439 ///
440 /// @return     GMM_STATUS.
441 /////////////////////////////////////////////////////////////////////////////////////
UnLockMAContextSyncMutex()442 GMM_STATUS GMM_STDCALL GmmLib::GmmMultiAdapterContext::UnLockMAContextSyncMutex()
443 {
444     if(MAContextSyncMutex)
445     {
446         ::ReleaseMutex(MAContextSyncMutex);
447         return GMM_SUCCESS;
448     }
449     else
450     {
451         return GMM_ERROR;
452     }
453 }
454 
455 /////////////////////////////////////////////////////////////////////////////////////
456 /// Member function of GmmMultiAdapterContext class for Locking Adpater's Mutex
457 /// SyncMutex to protect access of GmmLibContext
458 ///
459 /// @return     GMM_STATUS.
460 /////////////////////////////////////////////////////////////////////////////////////
LockSingletonContextSyncMutex(ADAPTER_BDF sBdf)461 GMM_STATUS GMM_STDCALL GmmLib::GmmMultiAdapterContext::LockSingletonContextSyncMutex(ADAPTER_BDF sBdf)
462 {
463     uint32_t AdapterIdx = GetAdapterIndex(sBdf);
464     if(AdapterIdx < MAX_NUM_ADAPTERS)
465     {
466         GMM_MUTEX_HANDLE SyncMutex = AdapterInfo[AdapterIdx].SyncMutex;
467 
468         if(SyncMutex)
469         {
470             while(WAIT_OBJECT_0 != ::WaitForSingleObject(SyncMutex, INFINITE))
471                 ;
472             return GMM_SUCCESS;
473         }
474         else
475         {
476             return GMM_ERROR;
477         }
478     }
479     else
480     {
481         return GMM_ERROR;
482     }
483 }
484 
485 /////////////////////////////////////////////////////////////////////////////////////
486 /// Member function of GmmMultiAdapterContext class for UnLocking Adpater's Mutex
487 /// SyncMutex to protect access of GmmLibContext
488 ///
489 /// @return     GMM_STATUS.
490 /////////////////////////////////////////////////////////////////////////////////////
UnlockSingletonContextSyncMutex(ADAPTER_BDF sBdf)491 GMM_STATUS GMM_STDCALL GmmLib::GmmMultiAdapterContext::UnlockSingletonContextSyncMutex(ADAPTER_BDF sBdf)
492 {
493     uint32_t AdapterIdx = GetAdapterIndex(sBdf);
494     if(AdapterIdx < MAX_NUM_ADAPTERS)
495     {
496         GMM_MUTEX_HANDLE SyncMutex = AdapterInfo[AdapterIdx].SyncMutex;
497         if(SyncMutex)
498         {
499             ::ReleaseMutex(SyncMutex);
500             return GMM_SUCCESS;
501         }
502         else
503         {
504             return GMM_ERROR;
505         }
506     }
507     else
508     {
509         return GMM_ERROR;
510     }
511 }
512 
513 #else // Non Win OS
514 
515 /////////////////////////////////////////////////////////////////////////////////////
516 /// Member function of GmmMultiAdapterContext class for Locking MultiAdapter Mutex
517 ///
518 /// @return     GMM_STATUS.
519 /////////////////////////////////////////////////////////////////////////////////////
LockMAContextSyncMutex()520 GMM_STATUS GMM_STDCALL GmmLib::GmmMultiAdapterContext::LockMAContextSyncMutex()
521 {
522     pthread_mutex_lock(&MAContextSyncMutex);
523     return GMM_SUCCESS;
524 }
525 
526 /////////////////////////////////////////////////////////////////////////////////////
527 /// Member function of GmmMultiAdapterContext class for UnLocking MultiAdapter Mutex
528 ///
529 /// @return     GMM_STATUS.
530 /////////////////////////////////////////////////////////////////////////////////////
UnLockMAContextSyncMutex()531 GMM_STATUS GMM_STDCALL GmmLib::GmmMultiAdapterContext::UnLockMAContextSyncMutex()
532 {
533     pthread_mutex_unlock(&MAContextSyncMutex);
534     return GMM_SUCCESS;
535 }
536 
537 /////////////////////////////////////////////////////////////////////////////////////
538 /// Member function of GmmMultiAdapterContext class for Locking Adpater's Mutex
539 ///
540 /// @return     GMM_STATUS.
541 /////////////////////////////////////////////////////////////////////////////////////
LockSingletonContextSyncMutex(ADAPTER_BDF sBdf)542 GMM_STATUS GMM_STDCALL GmmLib::GmmMultiAdapterContext::LockSingletonContextSyncMutex(ADAPTER_BDF sBdf)
543 {
544     uint32_t AdapterIdx = GetAdapterIndex(sBdf);
545     if(AdapterIdx < MAX_NUM_ADAPTERS)
546     {
547         pthread_mutex_lock(&AdapterInfo[AdapterIdx].SyncMutex);
548         return GMM_SUCCESS;
549     }
550     else
551     {
552         return GMM_ERROR;
553     }
554 }
555 
556 /////////////////////////////////////////////////////////////////////////////////////
557 /// Member function of GmmMultiAdapterContext class for UnLocking Adpater's Mutex
558 ///
559 /// @return     GMM_STATUS.
560 /////////////////////////////////////////////////////////////////////////////////////
UnlockSingletonContextSyncMutex(ADAPTER_BDF sBdf)561 GMM_STATUS GMM_STDCALL GmmLib::GmmMultiAdapterContext::UnlockSingletonContextSyncMutex(ADAPTER_BDF sBdf)
562 {
563     uint32_t AdapterIdx = GetAdapterIndex(sBdf);
564     if(AdapterIdx < MAX_NUM_ADAPTERS)
565     {
566         pthread_mutex_unlock(&AdapterInfo[AdapterIdx].SyncMutex);
567         return GMM_SUCCESS;
568     }
569     else
570     {
571         return GMM_ERROR;
572     }
573 }
574 
575 #endif //#ifdef _WIN32
576 
577 /////////////////////////////////////////////////////////////////////////////////////
578 /// Member function of GmmMultiAdapterContext class for Incrementing Adpater's Ref
579 /// Count
580 /// @param1     sBdf        Adpater's Bus, Device and Fucntion
581 /// @return     Current value of the ref count.
582 /////////////////////////////////////////////////////////////////////////////////////
IncrementRefCount(ADAPTER_BDF sBdf)583 int32_t GMM_STDCALL GmmLib::GmmMultiAdapterContext::IncrementRefCount(ADAPTER_BDF sBdf)
584 {
585     uint32_t AdapterIdx = GetAdapterIndex(sBdf);
586     if(AdapterIdx < MAX_NUM_ADAPTERS)
587     {
588         int32_t *Ref = &AdapterInfo[AdapterIdx].RefCount;
589 
590 #if defined(_WIN32)
591         return (InterlockedIncrement((LONG *)Ref) - 1); //InterLockedIncrement() returns incremented value
592 #elif defined(__GNUC__)
593         return (__sync_fetch_and_add(Ref, 1));
594 #endif
595     }
596     else
597     {
598         return 0;
599     }
600 }
601 
602 /////////////////////////////////////////////////////////////////////////////////////
603 /// Member function of GmmMultiAdapterContext class for Decrementing Adpater's Ref
604 /// Count
605 /// @param1     sBdf        Adpater's Bus, Device and Fucntion
606 /// @return     Current value of the ref count.
607 /////////////////////////////////////////////////////////////////////////////////////
DecrementRefCount(ADAPTER_BDF sBdf)608 int32_t GMM_STDCALL GmmLib::GmmMultiAdapterContext::DecrementRefCount(ADAPTER_BDF sBdf)
609 {
610     uint32_t AdapterIdx = GetAdapterIndex(sBdf);
611     if(AdapterIdx < MAX_NUM_ADAPTERS)
612     {
613         int32_t *Ref          = &AdapterInfo[AdapterIdx].RefCount;
614         int      CurrentValue = 0;
615         int      TargetValue  = 0;
616         do
617         {
618             CurrentValue = *Ref;
619             if(CurrentValue > 0)
620             {
621                 TargetValue = CurrentValue - 1;
622             }
623             else
624             {
625                 break;
626             }
627 #if defined(_WIN32)
628         } while(!(InterlockedCompareExchange((LONG *)Ref, TargetValue, CurrentValue) == CurrentValue));
629 #elif defined(__GNUC__)
630         } while(!__sync_bool_compare_and_swap(Ref, CurrentValue, TargetValue));
631 #endif
632 
633         return TargetValue;
634     }
635     else
636     {
637         return 0;
638     }
639 }
640 
641 #ifdef _WIN32
642 /////////////////////////////////////////////////////////////////////////
643 /// Get ProcessHeapVA Singleton HeapObj
644 /////////////////////////////////////////////////////////////////////////
GetSharedHeapObject()645 GMM_HEAP *GmmLib::Context::GetSharedHeapObject()
646 {
647     GMM_HEAP *pHeapObjOut = NULL;
648     // Obtain ProcessSingleton Lock
649 #if GMM_LIB_DLL_MA
650     pGmmMALibContext->LockSingletonContextSyncMutex(sBdf);
651 #else
652     GmmLib::Context::LockSingletonContextSyncMutex();
653 #endif
654 
655     //Check if the ProcessHeapCounter is 0 or not, if not 0 increment the counter and return the heapObj
656     // that is stored in the DLL Singleton context
657     if(ProcessHeapCounter)
658     {
659         ProcessHeapCounter++;
660         pHeapObjOut = pHeapObj;
661     }
662 
663     // Unlock ProcessSingleton Lock
664 #if GMM_LIB_DLL_MA
665     pGmmMALibContext->UnlockSingletonContextSyncMutex(sBdf);
666 #else
667     GmmLib::Context::UnlockSingletonContextSyncMutex();
668 #endif
669 
670     return pHeapObjOut;
671 }
672 /////////////////////////////////////////////////////////////////////////
673 /// Set ProcessHeapVA Singleton HeapObj
674 /////////////////////////////////////////////////////////////////////////
SetSharedHeapObject(GMM_HEAP ** pProcessHeapObj)675 uint32_t GmmLib::Context::SetSharedHeapObject(GMM_HEAP **pProcessHeapObj)
676 {
677     uint32_t DllClientsCount = 0;
678     // Obtain ProcessSingleton Lock
679 #if GMM_LIB_DLL_MA
680     pGmmMALibContext->LockSingletonContextSyncMutex(sBdf);
681 #else
682     GmmLib::Context::LockSingletonContextSyncMutex();
683 #endif
684 
685     if(pProcessHeapObj)
686     {
687         if(!ProcessHeapCounter)
688         {
689             // Setting it for the first time
690             ProcessHeapCounter++;
691             pHeapObj = *pProcessHeapObj;
692         }
693         else
694         {
695             ProcessHeapCounter++;
696             *pProcessHeapObj = pHeapObj;
697         }
698     }
699     else // Destroy the HeapObj Handle Case
700     {
701         ProcessHeapCounter--;
702         if(!ProcessHeapCounter)
703         {
704             // When all UMDs clients have called destroy
705             pHeapObj = NULL;
706         }
707     }
708 
709     DllClientsCount = ProcessHeapCounter;
710 
711     // Unlock ProcessSingleton Lock
712 #if GMM_LIB_DLL_MA
713     pGmmMALibContext->UnlockSingletonContextSyncMutex(sBdf);
714 #else
715     GmmLib::Context::UnlockSingletonContextSyncMutex();
716 #endif
717 
718     return DllClientsCount;
719 }
720 
721 /////////////////////////////////////////////////////////////////////////
722 /// Get ProcessGfxPartition
723 /////////////////////////////////////////////////////////////////////////
GetProcessGfxPartition(GMM_GFX_PARTITIONING * pProcessVA)724 void GmmLib::Context::GetProcessGfxPartition(GMM_GFX_PARTITIONING *pProcessVA)
725 {
726     // Obtain ProcessSingleton Lock
727 #if GMM_LIB_DLL_MA
728     pGmmMALibContext->LockSingletonContextSyncMutex(sBdf);
729 #else
730     GmmLib::Context::LockSingletonContextSyncMutex();
731 #endif
732 
733     //Check if the ProcessVACounter is 0 or not, if not 0 increment the counter and return the ProcessVA
734     // that is stored in the DLL Singleton context
735     if(ProcessVACounter)
736     {
737         ProcessVACounter++;
738         if(pProcessVA)
739         {
740             *pProcessVA = ProcessVA;
741         }
742     }
743 
744     // Unlock ProcessSingleton Lock
745 #if GMM_LIB_DLL_MA
746     pGmmMALibContext->UnlockSingletonContextSyncMutex(sBdf);
747 #else
748     GmmLib::Context::UnlockSingletonContextSyncMutex();
749 #endif
750 }
751 
752 /////////////////////////////////////////////////////////////////////////
753 /// Set ProcessGfxPartition
754 /////////////////////////////////////////////////////////////////////////
SetProcessGfxPartition(GMM_GFX_PARTITIONING * pProcessVA)755 void GmmLib::Context::SetProcessGfxPartition(GMM_GFX_PARTITIONING *pProcessVA)
756 {
757     // Obtain ProcessSingleton Lock
758 #if GMM_LIB_DLL_MA
759     pGmmMALibContext->LockSingletonContextSyncMutex(sBdf);
760 #else
761     GmmLib::Context::LockSingletonContextSyncMutex();
762 #endif
763 
764     if(pProcessVA)
765     {
766         if(!ProcessVACounter)
767         {
768             // Setting it for the first time
769             ProcessVACounter++;
770             ProcessVA = *pProcessVA;
771         }
772         else
773         {
774             ProcessVACounter++;
775             //Add code to return the stored value of ProcessVA when Escapes are removed
776         }
777     }
778     else // Reset the ProcessVA Case
779     {
780         ProcessVACounter--;
781         if(!ProcessVACounter)
782         {
783             // When all UMDs clients have called destroy
784             ProcessVA = {0};
785         }
786     }
787 
788     // Unlock ProcessSingleton Lock
789 #if GMM_LIB_DLL_MA
790     pGmmMALibContext->UnlockSingletonContextSyncMutex(sBdf);
791 #else
792     GmmLib::Context::UnlockSingletonContextSyncMutex();
793 #endif
794 }
795 
796 #endif // _WIN32
797 
798 #endif // GMM_LIB_DLL
799 
800 /////////////////////////////////////////////////////////////////////////////////////
801 /// Constructor to zero initialize the GmmLib::Context object
802 /////////////////////////////////////////////////////////////////////////////////////
Context()803 GmmLib::Context::Context()
804     : ClientType(),
805       pPlatformInfo(),
806       pTextureCalc(),
807       SkuTable(),
808       WaTable(),
809       GtSysInfo(),
810       pGmmKmdContext(),
811       pGmmUmdContext(),
812       pKmdHwDev(),
813       pUmdAdapter(),
814       pGmmCachePolicy()
815 {
816     memset(CachePolicy, 0, sizeof(CachePolicy));
817     memset(CachePolicyTbl, 0, sizeof(CachePolicyTbl));
818 
819     //Default initialize 64KB Page padding percentage.
820     AllowedPaddingFor64KbPagesPercentage = 10;
821     InternalGpuVaMax                     = 0;
822     AllowedPaddingFor64KBTileSurf        = 10;
823 #if(!defined(__GMM_KMD__) && !defined(GMM_UNIFIED_LIB))
824     pGmmGlobalClientContext = NULL;
825 #endif
826 
827 }
828 
829 /////////////////////////////////////////////////////////////////////////////////////
830 /// Destructor to release  GmmLib::Context object memory
831 /////////////////////////////////////////////////////////////////////////////////////
~Context()832 GmmLib::Context::~Context()
833 {
834 }
835 
836 /////////////////////////////////////////////////////////////////////////////////////
837 /// Member function to initialize the GmmLib::Context object with cache policy,
838 /// platform info, Texture calculator etc.
839 /// @param[in]  Platform: ref to platform
840 /// @param[in]  pSkuTable: ptr to sku table
841 /// @param[in]  pWaTable: ptr to workaround table
842 /// @param[in]  pGtSysInfo: ptr to gt system info
843 /// @param[in]  ClientType: client type such as dx, ogl, ocl etc
844 /// @return   GMM_SUCCESS if init is success, GMM_ERROR otherwise
845 /////////////////////////////////////////////////////////////////////////////////////
InitContext(const PLATFORM & Platform,const SKU_FEATURE_TABLE * pSkuTable,const WA_TABLE * pWaTable,const GT_SYSTEM_INFO * pGtSysInfo,GMM_CLIENT ClientType)846 GMM_STATUS GMM_STDCALL GmmLib::Context::InitContext(
847 const PLATFORM &         Platform,
848 const SKU_FEATURE_TABLE *pSkuTable,
849 const WA_TABLE *         pWaTable,
850 const GT_SYSTEM_INFO *   pGtSysInfo,
851 GMM_CLIENT               ClientType)
852 {
853     this->ClientType = ClientType;
854 
855     // Save the SKU and WA
856     this->SkuTable  = *pSkuTable;
857     this->WaTable   = *pWaTable;
858     this->GtSysInfo = *pGtSysInfo;
859 
860     this->pPlatformInfo = CreatePlatformInfo(Platform, false);
861 
862     OverrideSkuWa();
863 
864 
865     this->pGmmCachePolicy = CreateCachePolicyCommon();
866     if(this->pGmmCachePolicy == NULL)
867     {
868         return GMM_ERROR;
869     }
870 
871     this->pGmmCachePolicy->InitCachePolicy();
872 
873     this->pTextureCalc = CreateTextureCalc(Platform, false);
874     if(this->pTextureCalc == NULL)
875     {
876         return GMM_ERROR;
877     }
878 
879     return GMM_SUCCESS;
880 }
881 
882 /////////////////////////////////////////////////////////////////////////////////////
883 /// Member function to deallcoate the GmmLib::Context's cache policy, platform info,
884 /// Texture calculator etc.
885 /////////////////////////////////////////////////////////////////////////////////////
DestroyContext()886 void GMM_STDCALL GmmLib::Context::DestroyContext()
887 {
888     if(this->pGmmCachePolicy)
889     {
890             delete this->pGmmCachePolicy;
891             this->pGmmCachePolicy = NULL;
892     }
893 
894     if(this->pTextureCalc)
895     {
896             delete this->pTextureCalc;
897             this->pTextureCalc = NULL;
898     }
899 
900     if(this->pPlatformInfo)
901     {
902             delete this->pPlatformInfo;
903             this->pPlatformInfo = NULL;
904     }
905 }
906 
OverrideSkuWa()907 void GMM_STDCALL GmmLib::Context::OverrideSkuWa()
908 {
909     if((GFX_GET_CURRENT_PRODUCT(this->GetPlatformInfo().Platform) < IGFX_XE_HP_SDV))
910     {
911         SkuTable.FtrTileY = true;
912     }
913 
914     if(GFX_GET_CURRENT_PRODUCT(this->GetPlatformInfo().Platform) == IGFX_PVC)
915     {
916         SkuTable.Ftr57bGPUAddressing = true;
917     }
918 }
919 
CreateCachePolicyCommon()920 GMM_CACHE_POLICY *GMM_STDCALL GmmLib::Context::CreateCachePolicyCommon()
921 {
922     GMM_CACHE_POLICY *        pGmmCachePolicy = NULL;
923     GMM_CACHE_POLICY_ELEMENT *CachePolicy     = NULL;
924     CachePolicy                               = GetCachePolicyUsage();
925 
926     if(GetCachePolicyObj())
927     {
928         return GetCachePolicyObj();
929     }
930 
931     switch(GFX_GET_CURRENT_RENDERCORE(this->GetPlatformInfo().Platform))
932     {
933         case IGFX_GEN12LP_CORE:
934         case IGFX_GEN12_CORE:
935         case IGFX_XE_HP_CORE:
936 	case IGFX_XE_HPG_CORE:
937             if(GetSkuTable().FtrLocalMemory)
938             {
939                 pGmmCachePolicy = new GmmLib::GmmGen12dGPUCachePolicy(CachePolicy, this);
940             }
941             else
942             {
943                 pGmmCachePolicy = new GmmLib::GmmGen12CachePolicy(CachePolicy, this);
944             }
945             break;
946         case IGFX_GEN11_CORE:
947             pGmmCachePolicy = new GmmLib::GmmGen11CachePolicy(CachePolicy, this);
948             break;
949         case IGFX_GEN10_CORE:
950             pGmmCachePolicy = new GmmLib::GmmGen10CachePolicy(CachePolicy, this);
951             break;
952         case IGFX_GEN9_CORE:
953             pGmmCachePolicy = new GmmLib::GmmGen9CachePolicy(CachePolicy, this);
954             break;
955         default:
956             pGmmCachePolicy = new GmmLib::GmmGen8CachePolicy(CachePolicy, this);
957             break;
958     }
959 
960     if(!pGmmCachePolicy)
961     {
962         GMM_DPF_CRITICAL("unable to allocate memory for CachePolicy Object");
963     }
964 
965     return pGmmCachePolicy;
966 }
967 
CreateTextureCalc(PLATFORM Platform,bool Override)968 GMM_TEXTURE_CALC *GMM_STDCALL GmmLib::Context::CreateTextureCalc(PLATFORM Platform, bool Override)
969 {
970     if(!Override)
971     {
972         if(GetTextureCalc())
973         {
974             return GetTextureCalc();
975         }
976     }
977 
978     switch(GFX_GET_CURRENT_RENDERCORE(Platform))
979     {
980         case IGFX_GEN7_CORE:
981         case IGFX_GEN7_5_CORE:
982             return new GmmGen7TextureCalc(this);
983             break;
984         case IGFX_GEN8_CORE:
985             return new GmmGen8TextureCalc(this);
986             break;
987         case IGFX_GEN9_CORE:
988             return new GmmGen9TextureCalc(this);
989             break;
990         case IGFX_GEN10_CORE:
991             return new GmmGen10TextureCalc(this);
992             break;
993         case IGFX_GEN11_CORE:
994             return new GmmGen11TextureCalc(this);
995             break;
996         case IGFX_GEN12LP_CORE:
997         case IGFX_GEN12_CORE:
998         case IGFX_XE_HP_CORE:
999 	case IGFX_XE_HPG_CORE:
1000         default:
1001             return new GmmGen12TextureCalc(this);
1002             break;
1003     }
1004 }
1005 
CreatePlatformInfo(PLATFORM Platform,bool Override)1006 GMM_PLATFORM_INFO_CLASS *GMM_STDCALL GmmLib::Context::CreatePlatformInfo(PLATFORM Platform, bool Override)
1007 {
1008     GMM_DPF_ENTER;
1009 
1010     if(Override == false)
1011     {
1012         if(pPlatformInfo != NULL)
1013         {
1014             return pPlatformInfo;
1015         }
1016     }
1017    switch(GFX_GET_CURRENT_RENDERCORE(Platform))
1018     {
1019         case IGFX_GEN12LP_CORE:
1020         case IGFX_GEN12_CORE:
1021         case IGFX_XE_HP_CORE:
1022         case IGFX_XE_HPG_CORE:
1023             return new GmmLib::PlatformInfoGen12(Platform, (GMM_LIB_CONTEXT *)this);
1024             break;
1025         case IGFX_GEN11_CORE:
1026             return new GmmLib::PlatformInfoGen11(Platform, (GMM_LIB_CONTEXT *)this);
1027             break;
1028         case IGFX_GEN10_CORE:
1029             return new GmmLib::PlatformInfoGen10(Platform, (GMM_LIB_CONTEXT *)this);
1030             break;
1031         case IGFX_GEN9_CORE:
1032             return new GmmLib::PlatformInfoGen9(Platform, (GMM_LIB_CONTEXT *)this);
1033             break;
1034         default:
1035             return new GmmLib::PlatformInfoGen8(Platform, (GMM_LIB_CONTEXT *)this);
1036             break;
1037     }
1038 }
1039 
1040 //C - Wrappers
1041 /////////////////////////////////////////////////////////////////////////
1042 /// C-wrapper to get the PlatformInfo ptr
1043 /// @param[in]  pGmmLibContext: ptr to GMM_GLOBAL_CONTEXT
1044 /// @return   const PlatformInfo ptr
1045 /////////////////////////////////////////////////////////////////////////
GmmGetPlatformInfo(GMM_LIB_CONTEXT * pGmmLibContext)1046 const GMM_PLATFORM_INFO *GMM_STDCALL GmmGetPlatformInfo(GMM_LIB_CONTEXT *pGmmLibContext)
1047 {
1048     return (&pGmmLibContext->GetPlatformInfo());
1049 }
1050 
1051 /////////////////////////////////////////////////////////////////////////
1052 /// C-wrapper to get the cache policy element array ptr
1053 /// @param[in]  pGmmLibContext: ptr to GMM_GLOBAL_CONTEXT
1054 /// @return   const cache policy elment ptr
1055 /////////////////////////////////////////////////////////////////////////
GmmGetCachePolicyUsage(GMM_LIB_CONTEXT * pGmmLibContext)1056 const GMM_CACHE_POLICY_ELEMENT *GmmGetCachePolicyUsage(GMM_LIB_CONTEXT *pGmmLibContext)
1057 {
1058     return (pGmmLibContext->GetCachePolicyUsage());
1059 }
1060 
1061 /////////////////////////////////////////////////////////////////////////
1062 /// C-wrapper to get the texture calculation object ptr
1063 /// @param[in]  pGmmLibContext: ptr to GMM_GLOBAL_CONTEXT
1064 /// @return   TextureCalc ptr
1065 /////////////////////////////////////////////////////////////////////////
GmmGetTextureCalc(GMM_LIB_CONTEXT * pGmmLibContext)1066 GMM_TEXTURE_CALC *GmmGetTextureCalc(GMM_LIB_CONTEXT *pGmmLibContext)
1067 {
1068     return (pGmmLibContext->GetTextureCalc());
1069 }
1070 
1071 /////////////////////////////////////////////////////////////////////////
1072 /// C-wrapper to get the sku table ptr
1073 /// @param[in]  pGmmLibContext: ptr to GMM_GLOBAL_CONTEXT
1074 /// @return   const SkuTable ptr
1075 /////////////////////////////////////////////////////////////////////////
GmmGetSkuTable(GMM_LIB_CONTEXT * pGmmLibContext)1076 const SKU_FEATURE_TABLE *GmmGetSkuTable(GMM_LIB_CONTEXT *pGmmLibContext)
1077 {
1078     return (&pGmmLibContext->GetSkuTable());
1079 }
1080 
1081 /////////////////////////////////////////////////////////////////////////
1082 /// C-wrapper to get the Wa table ptr
1083 /// @param[in]  pGmmLibContext: ptr to GMM_GLOBAL_CONTEXT
1084 /// @return   const WaTable ptr
1085 /////////////////////////////////////////////////////////////////////////
GmmGetWaTable(GMM_LIB_CONTEXT * pGmmLibContext)1086 const WA_TABLE *GmmGetWaTable(GMM_LIB_CONTEXT *pGmmLibContext)
1087 {
1088     return (&pGmmLibContext->GetWaTable());
1089 }
1090 
1091 /////////////////////////////////////////////////////////////////////////
1092 /// C-wrapper to get the GT system info ptr
1093 /// @param[in]  pGmmLibContext: ptr to GMM_GLOBAL_CONTEXT
1094 /// @return   const GtSysInfo ptr
1095 /////////////////////////////////////////////////////////////////////////
GmmGetGtSysInfo(GMM_LIB_CONTEXT * pGmmLibContext)1096 const GT_SYSTEM_INFO *GmmGetGtSysInfo(GMM_LIB_CONTEXT *pGmmLibContext)
1097 {
1098     return (pGmmLibContext->GetGtSysInfoPtr());
1099 }
1100 
1101