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