1 /*==============================================================================
2 Copyright(c) 2019 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 Description: This file contains the class definitions for GmmPageTablePool
23              PageTable, and low-level Tables for user-mode PageTable management,
24              that is common for both Linux and Windows.
25 
26 ======================= end_copyright_notice ==================================*/
27 #pragma once
28 #include "External/Common/GmmPageTableMgr.h"
29 
30 #ifndef _WIN32
31 #include <pthread.h>
32 #include <string.h>
33 
34 // Internal Linux version of MSDK APIs.
InitializeCriticalSection(pthread_mutex_t * mutex)35 static inline void InitializeCriticalSection(pthread_mutex_t *mutex)
36 {
37     pthread_mutexattr_t Attr;
38     pthread_mutexattr_init(&Attr);
39     pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE);
40     pthread_mutex_init(mutex, &Attr);
41 }
42 
DeleteCriticalSection(pthread_mutex_t * mutex)43 static inline void DeleteCriticalSection(pthread_mutex_t *mutex)
44 {
45     pthread_mutex_destroy(mutex);
46 }
47 
EnterCriticalSection(pthread_mutex_t * mutex)48 static inline void EnterCriticalSection(pthread_mutex_t *mutex)
49 {
50     pthread_mutex_lock(mutex);
51 }
52 
LeaveCriticalSection(pthread_mutex_t * mutex)53 static inline void LeaveCriticalSection(pthread_mutex_t *mutex)
54 {
55     pthread_mutex_unlock(mutex);
56 }
57 
58 #ifndef _BitScanForwardDefined
_BitScanForward(uint32_t * index,uint32_t mask)59 static inline int _BitScanForward(uint32_t *index, uint32_t mask)
60 {
61     int i;
62 
63     i = __builtin_ffsl(mask);
64     if(i > 0)
65     {
66         *index = (uint32_t)(i - 1);
67         return i;
68     }
69     return 0;
70 }
71 #endif
72 #endif
73 
74 #define GMM_L1_SIZE(TTType, pGmmLibContext)  GMM_AUX_L1_SIZE(pGmmLibContext)
75 #define GMM_L1_SIZE_DWORD(TTType, pGmmLibContext) GMM_AUX_L1_SIZE_DWORD(pGmmLibContext)
76 #define GMM_L2_SIZE(TTType)                       GMM_AUX_L2_SIZE
77 #define GMM_L2_SIZE_DWORD(TTType)                 GMM_AUX_L2_SIZE_DWORD
78 #define GMM_L3_SIZE(TTType)                       GMM_AUX_L3_SIZE
79 #define GMM_L1_ENTRY_IDX(TTType, GfxAddress, pGmmLibContext) GMM_AUX_L1_ENTRY_IDX((GfxAddress), (pGmmLibContext))
80 #define GMM_L2_ENTRY_IDX(TTType, GfxAddress)                 GMM_AUX_L2_ENTRY_IDX((GfxAddress))
81 #define GMM_L3_ENTRY_IDX(TTType, GfxAddress)                 GMM_AUX_L3_ENTRY_IDX((GfxAddress))
82 
83 #ifdef GMM_ULT
84 #define GMM_L1_ENTRY_IDX_EXPORTED(TTType, GfxAddress, WA64KEx)    GMM_AUX_L1_ENTRY_IDX_EXPORTED((GfxAddress), WA64KEx)
85 #endif
86 
87 #ifdef __cplusplus
88 #include "External/Common/GmmMemAllocator.hpp"
89 
90 //HW provides single-set of TR/Aux-TT registers for non-privileged programming
91 //Engine-specific offsets are HW-updated with programmed values.
92 #define GET_L3ADROFFSET(TRTT, L3AdrOffset, pGmmLibContext) \
93            L3AdrOffset = 0x4200;
94 
95 
96 #define ASSIGN_POOLNODE(Pool, NodeIdx, PerTableNodes)    {       \
97     (Pool)->GetNodeUsageAtIndex((NodeIdx) / (32 *(PerTableNodes))) |= __BIT(((NodeIdx) / (PerTableNodes)) % 32);  \
98     (Pool)->GetNodeBBInfoAtIndex(NodeIdx) = SyncInfo();                              \
99     (Pool)->GetNumFreeNode() -= (PerTableNodes);                      \
100                                           }
101 
102 #define DEASSIGN_POOLNODE(PageTableMgr, UmdContext, Pool, NodeIdx, PerTableNodes)  {            \
103     (Pool)->GetNodeUsageAtIndex((NodeIdx) / (32 * (PerTableNodes))) &= ~__BIT(((NodeIdx) / (PerTableNodes)) % 32 );  \
104     (Pool)->GetNumFreeNode() += (PerTableNodes);                      \
105     if((Pool)->GetNumFreeNode() == PAGETABLE_POOL_MAX_NODES) {        \
106     PageTableMgr->__ReleaseUnusedPool((UmdContext));              \
107                                                     }             \
108                                           }
109 
110 namespace GmmLib
111 {
112 #define PAGETABLE_POOL_MAX_NODES         512                               //Max. number of L2/L1 tables pool contains
113 #define PAGETABLE_POOL_SIZE_IN_DWORD     PAGETABLE_POOL_MAX_NODES / 32
114 #define PAGETABLE_POOL_SIZE              PAGETABLE_POOL_MAX_NODES * PAGE_SIZE   //Pool for L2/L1 table allocation
115 #define AUX_L2TABLE_SIZE_IN_POOLNODES    8                                 //Aux L2 is 32KB
116 #define AUX_L1TABLE_SIZE_IN_POOLNODES    2                                 //Aux L1 is 8KB
117 #define PAGETABLE_POOL_MAX_UNUSED_SIZE   GMM_MBYTE(16)                     //Max. size of unused pool, driver keeps resident
118 
119 
120     //////////////////////////////////////////////////////////////////////////////////////////////
121     /// Contains functions and members for GmmPageTablePool.
122     /// PageTablePool is a Linked-list, provides common location for both Aux TT and TR-TT pages
123     /// Separate NodePool (linked-list element) kept for each PoolType, for cleaner management in
124     /// per-table size
125     /////////////////////////////////////////////////////////////////////////////////////////////
126     class GmmPageTablePool
127     {
128     private:
129                                        //PageTablePool allocation descriptor
130         GMM_RESOURCE_INFO* pGmmResInfo;
131         HANDLE             PoolHandle;
132         GMM_GFX_ADDRESS    PoolGfxAddress;
133         GMM_GFX_ADDRESS    CPUAddress;              //LMEM-cpuvisible adr
134 
135         POOL_TYPE         PoolType;       //Separate Node-pools for TR-L2, TR-L1, Aux-L2, Aux-L1 usages-
136 
137                                       //PageTablePool usage descriptors
138         int              NumFreeNodes;    //has value {0 to Pool_Max_nodes}
139         uint32_t*           NodeUsage;       //destined node state (updated during node assignment and removed based on destined state of L1/L2 Table
140                                           //that used the pool node)
141                                           //Aux-Pool node-usage tracked at every eighth/second node(for L2 vs L1)
142                                           //ie 1b per node for TR-table, 1b per 8-nodes for Aux-L2table, 1b per 2-nodes for AuxL1-table
143                                           //array size= POOL_SIZE_IN_DWORD for TR, =POOL_SIZE_IN_DWORD/8 for AuxL2, POOL_SIZE_IN_DWORD/2 for AuxL1
144 
145         SyncInfo*        NodeBBInfo;      //BB info for pending Gpu usage of each pool node
146                                           //array of size MaxPoolNodes for TR, =MaxPoolNodes / 8 for Aux, MaxPoolNodes / 2 for AuxL1
147 
148         SyncInfo         PoolBBInfo;      //BB info for Gpu usage of the Pool (most recent of pool node BB info)
149 
150         GmmPageTablePool* NextPool;       //Next node-Pool in the LinkedList
151         GmmClientContext    *pClientContext;    ///< ClientContext of the client creating this Object
152     public:
GmmPageTablePool()153         GmmPageTablePool() :
154             pGmmResInfo(NULL),
155             PoolHandle(),
156             PoolGfxAddress(0x0),
157             CPUAddress(0x0),
158             PoolType(POOL_TYPE_TRTTL1),
159             NumFreeNodes(PAGETABLE_POOL_MAX_NODES),
160             NodeUsage(NULL),
161             NodeBBInfo(NULL),
162             PoolBBInfo(),
163             NextPool(NULL),
164             pClientContext(NULL)
165         {
166 
167         }
GmmPageTablePool(HANDLE hAlloc,GMM_RESOURCE_INFO * pGmmRes,GMM_GFX_ADDRESS SysMem,POOL_TYPE Type)168         GmmPageTablePool(HANDLE hAlloc, GMM_RESOURCE_INFO* pGmmRes, GMM_GFX_ADDRESS SysMem, POOL_TYPE Type) :
169             GmmPageTablePool()
170         {
171             PoolHandle = hAlloc;
172             pGmmResInfo = pGmmRes;
173             PoolGfxAddress = SysMem;
174             CPUAddress = PoolGfxAddress;
175             NextPool = NULL;
176             NumFreeNodes = PAGETABLE_POOL_MAX_NODES;
177             PoolType = Type;
178             int DwordPoolSize = (Type == POOL_TYPE_AUXTTL1) ? PAGETABLE_POOL_SIZE_IN_DWORD / AUX_L1TABLE_SIZE_IN_POOLNODES
179                                         : (Type == POOL_TYPE_AUXTTL2) ? PAGETABLE_POOL_SIZE_IN_DWORD / AUX_L2TABLE_SIZE_IN_POOLNODES
180                                         : PAGETABLE_POOL_SIZE_IN_DWORD;
181             NodeUsage = new uint32_t[DwordPoolSize]();
182             NodeBBInfo = new SyncInfo[DwordPoolSize * 32]();
183             if (pGmmResInfo)
184             {
185                 pClientContext = pGmmResInfo->GetGmmClientContext();
186             }
187         }
GmmPageTablePool(HANDLE hAlloc,GMM_RESOURCE_INFO * pGmmRes,GMM_GFX_ADDRESS GfxAdr,GMM_GFX_ADDRESS CPUAdr,POOL_TYPE Type)188         GmmPageTablePool(HANDLE hAlloc, GMM_RESOURCE_INFO* pGmmRes, GMM_GFX_ADDRESS GfxAdr, GMM_GFX_ADDRESS CPUAdr, POOL_TYPE Type) :
189             GmmPageTablePool(hAlloc, pGmmRes, GfxAdr, Type)
190         {
191             CPUAddress = (CPUAdr != GfxAdr) ? CPUAdr : GfxAdr;
192         }
~GmmPageTablePool()193         ~GmmPageTablePool()
194         {
195             delete[] NodeUsage;
196             delete[] NodeBBInfo;
197         }
198 
InsertInList(GmmPageTablePool * NewNode)199         GmmPageTablePool* InsertInList(GmmPageTablePool* NewNode)
200         {
201             GmmPageTablePool *Node = this;
202             while (Node->NextPool)
203             {
204                 Node = Node->NextPool;
205             }
206             Node->NextPool = NewNode;
207             return Node->NextPool;
208         }
209 
InsertInListAtBegin(GmmPageTablePool * NewNode)210         GmmPageTablePool* InsertInListAtBegin(GmmPageTablePool* NewNode)
211         {
212             GmmPageTablePool *Node = this;
213             NewNode->NextPool = Node;
214             return NewNode;
215         }
216 
GetNextPool()217         GmmPageTablePool* &GetNextPool() { return NextPool; }
GetPoolHandle()218         HANDLE& GetPoolHandle() { return PoolHandle; }
GetPoolType()219         POOL_TYPE& GetPoolType() { return PoolType; }
GetNumFreeNode()220         int& GetNumFreeNode() { return NumFreeNodes; }
GetPoolBBInfo()221         SyncInfo& GetPoolBBInfo() { return PoolBBInfo; }
GetNodeUsageAtIndex(int j)222         uint32_t& GetNodeUsageAtIndex(int j) { return NodeUsage[j]; }
GetNodeBBInfoAtIndex(int j)223         SyncInfo& GetNodeBBInfoAtIndex(int j)
224         {
225             int BBInfoNodeIdx = (PoolType == POOL_TYPE_AUXTTL1) ? j / AUX_L1TABLE_SIZE_IN_POOLNODES
226                 : (PoolType == POOL_TYPE_AUXTTL2) ? j / AUX_L2TABLE_SIZE_IN_POOLNODES
227                 : j;
228             return NodeBBInfo[BBInfoNodeIdx];
229         }
GetGfxAddress()230         GMM_GFX_ADDRESS GetGfxAddress() { return PoolGfxAddress; }
GetCPUAddress()231         GMM_GFX_ADDRESS GetCPUAddress() { return CPUAddress; }
GetGmmResInfo()232         GMM_RESOURCE_INFO* &GetGmmResInfo() { return pGmmResInfo; }
IsPoolInUse(SyncInfo BBInfo)233         bool IsPoolInUse(SyncInfo BBInfo) {
234             if (NumFreeNodes < PAGETABLE_POOL_MAX_NODES ||
235                 (PoolBBInfo.BBQueueHandle == BBInfo.BBQueueHandle &&
236                     PoolBBInfo.BBFence == BBInfo.BBFence + 1)) //Pool will be used by next BB submission, freeing it will cause page fault
237             {
238                 return true;
239             }
240             return false;
241         }
242         bool __IsUnusedTRTTPoolOverLimit(GMM_GFX_SIZE_T * OverLimitSize);
243         void ClearBBReference(void * BBQHandle);
244         GMM_STATUS __DestroyPageTablePool(void * DeviceCallbacks,HANDLE hCsr);
245     };
246 
247     //////////////////////////////////////////////////////////////////////////////////////////////
248     /// Contains functions and members for Table.
249     /// Table defines basic building block for tables at different page-table levels
250     /////////////////////////////////////////////////////////////////////////////////////////////
251     class Table
252     {
253     protected:
254         GMM_PAGETABLEPool *PoolElem;              //L2 Pool ptr different for L2Tables when Pool_nodes <512
255         int             PoolNodeIdx;              //pool node idx used for L2 Table
256         SyncInfo             BBInfo;              //BB Handle/fence using Table
257         uint32_t*          UsedEntries;              //Tracks which L1/L2 entries are being used
258                                                   //array size GMM_L1_SIZE_DWORD(TT-type) for LastLevelTable, MidLeveltable(??)
259                                                   //array of 1024/32=32 DWs for TR-table, 4096/32 =512 for Aux-Table
260     public:
Table()261         Table() :
262             PoolElem(NULL),
263             PoolNodeIdx(),
264             BBInfo(),
265             UsedEntries(NULL)
266         {
267         }
GetNodeIdx()268         int& GetNodeIdx() { return  PoolNodeIdx; }
GetPool()269         GmmPageTablePool* &GetPool() { return PoolElem; }
GetCPUAddress()270         GMM_GFX_ADDRESS GetCPUAddress() { return (PoolElem->GetCPUAddress() + (PoolNodeIdx * PAGE_SIZE)); }
GetBBInfo()271         SyncInfo& GetBBInfo() { return BBInfo; }
GetUsedEntries()272         uint32_t* &GetUsedEntries() { return UsedEntries; }
273         bool TrackTableUsage(TT_TYPE Type, bool IsL1, GMM_GFX_ADDRESS TileAdr, bool NullMapped,GMM_LIB_CONTEXT* pGmmLibContext);
274         bool IsTableNullMapped(TT_TYPE Type, bool IsL1, GMM_GFX_ADDRESS TileAdr,GMM_LIB_CONTEXT *pGmmLibContext);
275         void UpdatePoolFence(GMM_UMD_SYNCCONTEXT * UmdContext, bool ClearNode);
276     };
277 
278     //////////////////////////////////////////////////////////////////////////////////////////////
279     /// Contains functions and members for LastLevelTable.
280     /// LastLevelTable defines leaf level tables in multi-level pageTable structure
281     /////////////////////////////////////////////////////////////////////////////////////////////
282     class LastLevelTable : public Table
283     {
284     private:
285         uint32_t         L2eIdx;
286         LastLevelTable *pNext;
287 
288     public:
LastLevelTable()289         LastLevelTable() : Table(),
290             L2eIdx()                             //Pass in Aux vs TR table's GMM_L2_SIZE and initialize L2eIdx?
291         {
292             pNext = NULL;
293         }
294 
LastLevelTable(GMM_PAGETABLEPool * Elem,int NodeIdx,int DwordL1e,int L2eIndex)295         LastLevelTable(GMM_PAGETABLEPool* Elem, int NodeIdx, int DwordL1e, int L2eIndex)
296             : LastLevelTable()
297         {
298             PoolElem = Elem;
299             PoolNodeIdx = NodeIdx;
300             BBInfo = Elem->GetNodeBBInfoAtIndex(NodeIdx);
301             L2eIdx = L2eIndex;
302             pNext = NULL;
303             UsedEntries = new uint32_t[DwordL1e]();
304         }
~LastLevelTable()305         ~LastLevelTable()
306         {
307             delete[] UsedEntries;
308         }
309 
GetL2eIdx()310         int GetL2eIdx() {
311             return L2eIdx;
312         }
313 
Next()314         LastLevelTable* &Next() {
315             return pNext;
316         }
317     };
318 
319     //////////////////////////////////////////////////////////////////////////////////////////////
320     /// Contains functions and members for MidLevelTable.
321     /// MidLevelTable defines secondary level tables in multi-level pageTable structure
322     /////////////////////////////////////////////////////////////////////////////////////////////
323     class MidLevelTable : public Table
324     {
325     private:
326         LastLevelTable  *pTTL1;                    //linked list of L1 tables
327 
328     public:
MidLevelTable()329         MidLevelTable() :Table()
330         {
331             pTTL1 = NULL;
332         }
MidLevelTable(GMM_PAGETABLEPool * Pool,int NodeIdx,SyncInfo Info)333         MidLevelTable(GMM_PAGETABLEPool *Pool, int NodeIdx, SyncInfo Info) : MidLevelTable()
334         {
335             PoolElem = Pool;
336             BBInfo = Info;
337             PoolNodeIdx = NodeIdx;
338         }
~MidLevelTable()339         ~MidLevelTable()
340         {
341             if (pTTL1)
342             {
343                 LastLevelTable* item = pTTL1;
344 
345                 while (item)
346                 {
347                     LastLevelTable* nextItem = item->Next();
348                     delete item;
349                     item = nextItem;
350                 }
351 
352                 pTTL1 = NULL;
353             }
354         }
355         LastLevelTable* GetL1Table(GMM_GFX_SIZE_T L2eIdx, LastLevelTable** Prev = NULL)
356         {
357             LastLevelTable* pL1Tbl = pTTL1;
358             LastLevelTable* PrevL1Tbl = NULL;
359 
360             while (pL1Tbl)
361             {
362                 if (pL1Tbl->GetL2eIdx() == L2eIdx)
363                 {
364                     break;
365                 }
366                 PrevL1Tbl = pL1Tbl;
367                 pL1Tbl = pL1Tbl->Next();
368             }
369 
370             //if requested, save previous node in linked-list
371             if (Prev)
372             {
373                 *Prev = PrevL1Tbl;
374             }
375             return pL1Tbl;
376         }
InsertInList(LastLevelTable * pL1Tbl)377         void InsertInList(LastLevelTable* pL1Tbl)
378         {
379             LastLevelTable* Prev = pTTL1;
380 
381             //Insert at end
382             while (Prev && Prev->Next())
383             {
384                 Prev = Prev->Next();
385             }
386 
387             if (Prev)
388             {
389                 Prev->Next() = pL1Tbl;
390             }
391             else
392             {
393                 pTTL1 = pL1Tbl;
394             }
395         }
DeleteFromList(LastLevelTable * pL1Tbl,LastLevelTable * PrevL1Tbl)396         void DeleteFromList(LastLevelTable* pL1Tbl, LastLevelTable* PrevL1Tbl)
397         {
398             //Save next L1Table in list, before deleting current one
399             if (pL1Tbl)
400             {
401                 if (PrevL1Tbl)
402                 {
403                     PrevL1Tbl->Next() = pL1Tbl->Next();
404                 }
405                 else
406                 {
407                     pTTL1 = pL1Tbl->Next();
408                 }
409 
410                 delete pL1Tbl;
411             }
412         }
413     };
414 
415     /////////////////////////////////////////////////////
416     /// Contains functions and members for PageTable.
417     /// PageTable defines multi-level pageTable
418     /////////////////////////////////////////////////////
419     class PageTable :
420         public GmmMemAllocator
421     {
422     protected:
423         const TT_TYPE TTType;                      //PageTable is AuxTT
424         const int NodesPerTable;                   //Aux L2/L3 has 32KB size, Aux L1 has 4KB -can't use as selector for PageTable is AuxTT
425                                                    // 1 node for TR-table, 8 nodes for Aux-Table L2, 2 nodes for Aux-table L1
426         //Root Table structure
427         struct RootTable
428         {
429             GMM_RESOURCE_INFO* pGmmResInfo;
430             HANDLE         L3Handle;
431             GMM_GFX_ADDRESS  GfxAddress;              //L3 Table Adr CPU equivalent GPU addr
432             GMM_GFX_ADDRESS  CPUAddress;              //LMEM-cpuvisible adr
433             bool        NeedRegisterUpdate;        //True @ L3 allocation, False when L3AdrRegWrite done
434             SyncInfo        BBInfo;
RootTableRootTable435             RootTable() : pGmmResInfo(NULL), L3Handle(NULL), GfxAddress(0), CPUAddress(0), NeedRegisterUpdate(false), BBInfo() {}
436         } TTL3;
437 
438         MidLevelTable*   pTTL2;                      //array of L2-Tables
439 
440     public:
441 #ifdef _WIN32
442         CRITICAL_SECTION    TTLock;                  //synchronized access of PageTable obj
443 #else
444         pthread_mutex_t TTLock;
445 #endif
446 
447         GmmPageTableMgr*  PageTableMgr;
448         GmmClientContext    *pClientContext;
449 
PageTable(int Size,int NumL3e,TT_TYPE flag)450         PageTable(int Size, int NumL3e, TT_TYPE flag) :
451             TTType(flag),
452 	    NodesPerTable(Size / PAGE_SIZE)
453         {
454             PageTableMgr = NULL;
455             pClientContext = NULL;
456             InitializeCriticalSection(&TTLock);
457 
458             pTTL2 = new MidLevelTable[NumL3e];
459         }
460 
~PageTable()461         ~PageTable()
462         {
463             delete[] pTTL2;
464 
465             DeleteCriticalSection(&TTLock);
466         }
467 
GetGmmLibContext()468 	inline GMM_LIB_CONTEXT* GetGmmLibContext()
469         {
470             return pClientContext->GetLibContext();
471         }
472 
GetL3Address()473         GMM_GFX_ADDRESS GetL3Address() { return TTL3.GfxAddress; }
GetRegisterStatus()474         bool &GetRegisterStatus() { return TTL3.NeedRegisterUpdate; }
475         GMM_STATUS AllocateL3Table(uint32_t L3TableSize, uint32_t L3AddrAlignment);
476         GMM_STATUS DestroyL3Table();
477         void AllocateL1L2Table(GMM_GFX_ADDRESS TileAddr, GMM_GFX_ADDRESS * L1TableAdr, GMM_GFX_ADDRESS * L2TableAdr);
478         void AllocateDummyTables(GmmLib::Table **L2Table, GmmLib::Table **L1Table);
479         void GetL1L2TableAddr(GMM_GFX_ADDRESS TileAddr, GMM_GFX_ADDRESS * L1TableAdr, GMM_GFX_ADDRESS* L2TableAdr);
480         uint8_t GetMappingType(GMM_GFX_ADDRESS GfxVA, GMM_GFX_SIZE_T Size, GMM_GFX_ADDRESS& LastAddr);
GetL3Handle()481         HANDLE GetL3Handle() { return TTL3.L3Handle; }
482     };
483 
484     //////////////////////////////////////////////////////////////////////////////////////////////
485     /// Contains functions and members for AuxTable.
486     /// AuxTable defines PageTable for translating VA->AuxVA, ie defines page-walk to get address
487     /// of CCS-cacheline containing auxiliary data (compression tag, etc) for some resource
488     /////////////////////////////////////////////////////////////////////////////////////////////
489     class AuxTable : public PageTable
490     {
491     public:
492         const int L1Size;
493         Table* NullL2Table;
494         Table* NullL1Table;
495         GMM_GFX_ADDRESS NullCCSTile;
AuxTable()496         AuxTable() : PageTable(8 * PAGE_SIZE, GMM_AUX_L3_SIZE, TT_TYPE::AUXTT),
497             L1Size(2 * PAGE_SIZE)
498         {
499             NullL2Table = nullptr;
500             NullL1Table = nullptr;
501             NullCCSTile = 0;
502         }
503         GMM_STATUS InvalidateTable(GMM_UMD_SYNCCONTEXT * UmdContext, GMM_GFX_ADDRESS BaseAdr, GMM_GFX_SIZE_T Size, uint8_t DoNotWait);
504 
505         GMM_STATUS MapValidEntry(GMM_UMD_SYNCCONTEXT *UmdContext, GMM_GFX_ADDRESS BaseAdr, GMM_GFX_SIZE_T BaseSize,
506                                  GMM_RESOURCE_INFO* BaseResInfo, GMM_GFX_ADDRESS AuxVA, GMM_RESOURCE_INFO* AuxResInfo, uint64_t PartialData, uint8_t DoNotWait);
507 
508         GMM_STATUS MapNullCCS(GMM_UMD_SYNCCONTEXT *UmdContext, GMM_GFX_ADDRESS BaseAdr, GMM_GFX_SIZE_T Size, uint64_t PartialL1e, uint8_t DoNotWait);
509 
510         GMM_AUXTTL1e CreateAuxL1Data(GMM_RESOURCE_INFO* BaseResInfo);
511         GMM_GFX_ADDRESS GMM_INLINE __GetCCSCacheline(GMM_RESOURCE_INFO* BaseResInfo, GMM_GFX_ADDRESS BaseAdr, GMM_RESOURCE_INFO* AuxResInfo,
512                                                      GMM_GFX_ADDRESS AuxVA, GMM_GFX_SIZE_T AdrOffset);
513 
514     };
515 
516 typedef struct _GMM_DEVICE_ALLOC {
517     uint32_t            Size;
518     uint32_t            Alignment;
519     HANDLE              Handle;
520     GMM_GFX_ADDRESS     GfxVA;
521     GMM_GFX_ADDRESS     CPUVA;
522     void *              Priv;
523     HANDLE              hCsr;
524 } GMM_DEVICE_ALLOC;
525 
526 typedef struct _GMM_DEVICE_DEALLOC {
527     HANDLE              Handle;
528     GMM_GFX_ADDRESS     GfxVA;
529     void *              Priv;
530     HANDLE              hCsr;
531 } GMM_DEVICE_DEALLOC;
532 
533 GMM_STATUS __GmmDeviceAlloc(GmmClientContext            *pClientContext,
534                             GMM_DEVICE_CALLBACKS_INT    *pDeviceCbInt,
535                             GMM_DEVICE_ALLOC            *pAlloc);
536 
537 GMM_STATUS __GmmDeviceDealloc(GMM_CLIENT                ClientType,
538                               GMM_DEVICE_CALLBACKS_INT  *DeviceCb,
539                               GMM_DEVICE_DEALLOC        *pDealloc,
540                               GmmClientContext *pClientContext);
541 }
542 #endif  // #ifdef __cplusplus
543 
544