File: GmmUmdTranslationTable.h

package info (click to toggle)
intel-gmmlib 20.4.1%2Bds1-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 4,524 kB
  • sloc: cpp: 52,910; ansic: 5,587; makefile: 6
file content (541 lines) | stat: -rw-r--r-- 22,109 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
/*==============================================================================
Copyright(c) 2019 Intel Corporation

Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files(the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and / or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

Description: This file contains the class definitions for GmmPageTablePool
             PageTable, and low-level Tables for user-mode PageTable management,
             that is common for both Linux and Windows.

======================= end_copyright_notice ==================================*/
#pragma once
#include "External/Common/GmmPageTableMgr.h"

#ifdef __linux__
#include <pthread.h>
#include <string.h>

// Internal Linux version of MSDK APIs.
static inline void InitializeCriticalSection(pthread_mutex_t *mutex)
{
    pthread_mutexattr_t Attr;
    pthread_mutexattr_init(&Attr);
    pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE);
    pthread_mutex_init(mutex, &Attr);
}

static inline void DeleteCriticalSection(pthread_mutex_t *mutex)
{
    pthread_mutex_destroy(mutex);
}

static inline void EnterCriticalSection(pthread_mutex_t *mutex)
{
    pthread_mutex_lock(mutex);
}

static inline void LeaveCriticalSection(pthread_mutex_t *mutex)
{
    pthread_mutex_unlock(mutex);
}

#ifndef _BitScanForwardDefined
static inline int _BitScanForward(uint32_t *index, uint32_t mask)
{
    int i;

#ifdef __ANDROID__
    i = ffs(mask);
#else
    i = ffsl(mask);
#endif

    if(i > 0)
    {
        *index = (uint32_t)(i - 1);
        return i;
    }
    return 0;
}
#endif
#endif

#define GMM_L1_SIZE(TTType, pGmmLibContext)       GMM_AUX_L1_SIZE(pGmmLibContext) 
#define GMM_L1_SIZE_DWORD(TTType, pGmmLibContext) GMM_AUX_L1_SIZE_DWORD(pGmmLibContext)
#define GMM_L2_SIZE(TTType)                       GMM_AUX_L2_SIZE
#define GMM_L2_SIZE_DWORD(TTType)                 GMM_AUX_L2_SIZE_DWORD 
#define GMM_L3_SIZE(TTType)                       GMM_AUX_L3_SIZE 
#define GMM_L1_ENTRY_IDX(TTType, GfxAddress, pGmmLibContext) GMM_AUX_L1_ENTRY_IDX((GfxAddress), (pGmmLibContext)) 
#define GMM_L2_ENTRY_IDX(TTType, GfxAddress)                 GMM_AUX_L2_ENTRY_IDX((GfxAddress)) 
#define GMM_L3_ENTRY_IDX(TTType, GfxAddress)                 GMM_AUX_L3_ENTRY_IDX((GfxAddress)) 

#ifdef GMM_ULT
#define GMM_L1_ENTRY_IDX_EXPORTED(TTType, GfxAddress, WA64KEx)    GMM_AUX_L1_ENTRY_IDX_EXPORTED((GfxAddress), WA64KEx) 
#endif

#ifdef __cplusplus
#include "External/Common/GmmMemAllocator.hpp"

//HW provides single-set of TR/Aux-TT registers for non-privileged programming
//Engine-specific offsets are HW-updated with programmed values.
#define GET_L3ADROFFSET(TRTT, L3AdrOffset) \
           L3AdrOffset = 0x4200;            


#define ASSIGN_POOLNODE(Pool, NodeIdx, PerTableNodes)    {       \
    (Pool)->GetNodeUsageAtIndex((NodeIdx) / (32 *(PerTableNodes))) |= __BIT(((NodeIdx) / (PerTableNodes)) % 32);  \
    (Pool)->GetNodeBBInfoAtIndex(NodeIdx) = SyncInfo();                              \
    (Pool)->GetNumFreeNode() -= (PerTableNodes);                      \
                                          }

#define DEASSIGN_POOLNODE(PageTableMgr, UmdContext, Pool, NodeIdx, PerTableNodes)  {            \
    (Pool)->GetNodeUsageAtIndex((NodeIdx) / (32 * (PerTableNodes))) &= ~__BIT(((NodeIdx) / (PerTableNodes)) % 32 );  \
    (Pool)->GetNumFreeNode() += (PerTableNodes);                      \
    if((Pool)->GetNumFreeNode() == PAGETABLE_POOL_MAX_NODES) {        \
    PageTableMgr->__ReleaseUnusedPool((UmdContext));              \
                                                    }             \
                                          }

namespace GmmLib
{
#define PAGETABLE_POOL_MAX_NODES         512                               //Max. number of L2/L1 tables pool contains
#define PAGETABLE_POOL_SIZE_IN_DWORD     PAGETABLE_POOL_MAX_NODES / 32
#define PAGETABLE_POOL_SIZE              PAGETABLE_POOL_MAX_NODES * PAGE_SIZE   //Pool for L2/L1 table allocation
#define AUX_L2TABLE_SIZE_IN_POOLNODES    8                                 //Aux L2 is 32KB
#define AUX_L1TABLE_SIZE_IN_POOLNODES    2                                 //Aux L1 is 8KB
#define PAGETABLE_POOL_MAX_UNUSED_SIZE   GMM_MBYTE(16)                     //Max. size of unused pool, driver keeps resident


    //////////////////////////////////////////////////////////////////////////////////////////////
    /// Contains functions and members for GmmPageTablePool. 
    /// PageTablePool is a Linked-list, provides common location for both Aux TT and TR-TT pages
    /// Separate NodePool (linked-list element) kept for each PoolType, for cleaner management in 
    /// per-table size
    /////////////////////////////////////////////////////////////////////////////////////////////
    class GmmPageTablePool
    {
    private:
                                       //PageTablePool allocation descriptor
        GMM_RESOURCE_INFO* pGmmResInfo;   
        HANDLE             PoolHandle;
        GMM_GFX_ADDRESS    PoolGfxAddress;
        GMM_GFX_ADDRESS    CPUAddress;              //LMEM-cpuvisible adr

        POOL_TYPE         PoolType;       //Separate Node-pools for TR-L2, TR-L1, Aux-L2, Aux-L1 usages-  

                                      //PageTablePool usage descriptors
        int              NumFreeNodes;    //has value {0 to Pool_Max_nodes}
        uint32_t*           NodeUsage;       //destined node state (updated during node assignment and removed based on destined state of L1/L2 Table 
                                          //that used the pool node) 
                                          //Aux-Pool node-usage tracked at every eighth/second node(for L2 vs L1) 
                                          //ie 1b per node for TR-table, 1b per 8-nodes for Aux-L2table, 1b per 2-nodes for AuxL1-table
                                          //array size= POOL_SIZE_IN_DWORD for TR, =POOL_SIZE_IN_DWORD/8 for AuxL2, POOL_SIZE_IN_DWORD/2 for AuxL1

        SyncInfo*        NodeBBInfo;      //BB info for pending Gpu usage of each pool node
                                          //array of size MaxPoolNodes for TR, =MaxPoolNodes / 8 for Aux, MaxPoolNodes / 2 for AuxL1

        SyncInfo         PoolBBInfo;      //BB info for Gpu usage of the Pool (most recent of pool node BB info)

        GmmPageTablePool* NextPool;       //Next node-Pool in the LinkedList
        GmmClientContext    *pClientContext;    ///< ClientContext of the client creating this Object
    public:
        GmmPageTablePool() :
            pGmmResInfo(NULL),
            PoolHandle(),
            PoolGfxAddress(0x0),
            CPUAddress(0x0),
            PoolType(POOL_TYPE_TRTTL1),
            NumFreeNodes(PAGETABLE_POOL_MAX_NODES),
            NodeUsage(NULL),
            NodeBBInfo(NULL),
            PoolBBInfo(),
            NextPool(NULL),
            pClientContext(NULL)
        {

        }
        GmmPageTablePool(HANDLE hAlloc, GMM_RESOURCE_INFO* pGmmRes, GMM_GFX_ADDRESS SysMem, POOL_TYPE Type) :
            GmmPageTablePool()
        {
            PoolHandle = hAlloc;
            pGmmResInfo = pGmmRes;
            PoolGfxAddress = SysMem;
            CPUAddress = PoolGfxAddress;
            NextPool = NULL;
            NumFreeNodes = PAGETABLE_POOL_MAX_NODES;
            PoolType = Type;
            int DwordPoolSize = (Type == POOL_TYPE_AUXTTL1) ? PAGETABLE_POOL_SIZE_IN_DWORD / AUX_L1TABLE_SIZE_IN_POOLNODES
                                        : (Type == POOL_TYPE_AUXTTL2) ? PAGETABLE_POOL_SIZE_IN_DWORD / AUX_L2TABLE_SIZE_IN_POOLNODES
                                        : PAGETABLE_POOL_SIZE_IN_DWORD;
            NodeUsage = new uint32_t[DwordPoolSize]();
            NodeBBInfo = new SyncInfo[DwordPoolSize * 32]();
            if (pGmmResInfo)
            {
                pClientContext = pGmmResInfo->GetGmmClientContext();
            }
        }
        GmmPageTablePool(HANDLE hAlloc, GMM_RESOURCE_INFO* pGmmRes, GMM_GFX_ADDRESS GfxAdr, GMM_GFX_ADDRESS CPUAdr, POOL_TYPE Type) :
            GmmPageTablePool(hAlloc, pGmmRes, GfxAdr, Type)
        {
            CPUAddress = (CPUAdr != GfxAdr) ? CPUAdr : GfxAdr;
        }
        ~GmmPageTablePool()
        {
            delete[] NodeUsage;
            delete[] NodeBBInfo;
        }

        GmmPageTablePool* InsertInList(GmmPageTablePool* NewNode)
        {
            GmmPageTablePool *Node = this;
            while (Node->NextPool)
            {
                Node = Node->NextPool;
            }
            Node->NextPool = NewNode;
            return Node->NextPool;
        }

        GmmPageTablePool* InsertInListAtBegin(GmmPageTablePool* NewNode)
        {
            GmmPageTablePool *Node = this;
            NewNode->NextPool = Node;
            return NewNode;
        }

        GmmPageTablePool* &GetNextPool() { return NextPool; }
        HANDLE& GetPoolHandle() { return PoolHandle; }
        POOL_TYPE& GetPoolType() { return PoolType; }
        int& GetNumFreeNode() { return NumFreeNodes; }
        SyncInfo& GetPoolBBInfo() { return PoolBBInfo; }
        uint32_t& GetNodeUsageAtIndex(int j) { return NodeUsage[j]; }
        SyncInfo& GetNodeBBInfoAtIndex(int j)
        {
            int BBInfoNodeIdx = (PoolType == POOL_TYPE_AUXTTL1) ? j / AUX_L1TABLE_SIZE_IN_POOLNODES
                : (PoolType == POOL_TYPE_AUXTTL2) ? j / AUX_L2TABLE_SIZE_IN_POOLNODES
                : j;
            return NodeBBInfo[BBInfoNodeIdx];
        }
        GMM_GFX_ADDRESS GetGfxAddress() { return PoolGfxAddress; }
        GMM_GFX_ADDRESS GetCPUAddress() { return CPUAddress; }
        GMM_RESOURCE_INFO* &GetGmmResInfo() { return pGmmResInfo; }
        bool IsPoolInUse(SyncInfo BBInfo) {
            if (NumFreeNodes < PAGETABLE_POOL_MAX_NODES ||
                (PoolBBInfo.BBQueueHandle == BBInfo.BBQueueHandle &&
                    PoolBBInfo.BBFence == BBInfo.BBFence + 1)) //Pool will be used by next BB submission, freeing it will cause page fault
            {
                return true;
            }
            return false;
        }
        bool __IsUnusedTRTTPoolOverLimit(GMM_GFX_SIZE_T * OverLimitSize);
        void ClearBBReference(void * BBQHandle);
        GMM_STATUS __DestroyPageTablePool(void * DeviceCallbacks,HANDLE hCsr);
    };

    //////////////////////////////////////////////////////////////////////////////////////////////
    /// Contains functions and members for Table. 
    /// Table defines basic building block for tables at different page-table levels
    /////////////////////////////////////////////////////////////////////////////////////////////
    class Table
    {
    protected:
        GMM_PAGETABLEPool *PoolElem;              //L2 Pool ptr different for L2Tables when Pool_nodes <512
        int             PoolNodeIdx;              //pool node idx used for L2 Table
        SyncInfo             BBInfo;              //BB Handle/fence using Table
        uint32_t*          UsedEntries;              //Tracks which L1/L2 entries are being used
                                                  //array size GMM_L1_SIZE_DWORD(TT-type) for LastLevelTable, MidLeveltable(??)
                                                  //array of 1024/32=32 DWs for TR-table, 4096/32 =512 for Aux-Table
    public:
        Table() :
            PoolElem(NULL),
            PoolNodeIdx(),
            BBInfo(),
            UsedEntries(NULL)
        {
        }
        int& GetNodeIdx() { return  PoolNodeIdx; }
        GmmPageTablePool* &GetPool() { return PoolElem; }
        GMM_GFX_ADDRESS GetCPUAddress() { return (PoolElem->GetCPUAddress() + (PoolNodeIdx * PAGE_SIZE)); }
        SyncInfo& GetBBInfo() { return BBInfo; }
        uint32_t* &GetUsedEntries() { return UsedEntries; }
        bool TrackTableUsage(TT_TYPE Type, bool IsL1, GMM_GFX_ADDRESS TileAdr, bool NullMapped);
        bool IsTableNullMapped(TT_TYPE Type, bool IsL1, GMM_GFX_ADDRESS TileAdr);
        void UpdatePoolFence(GMM_UMD_SYNCCONTEXT * UmdContext, bool ClearNode);
    };

    //////////////////////////////////////////////////////////////////////////////////////////////
    /// Contains functions and members for LastLevelTable. 
    /// LastLevelTable defines leaf level tables in multi-level pageTable structure
    /////////////////////////////////////////////////////////////////////////////////////////////
    class LastLevelTable : public Table
    {
    private:
        uint32_t         L2eIdx;
        LastLevelTable *pNext;

    public:
        LastLevelTable() : Table(),
            L2eIdx()                             //Pass in Aux vs TR table's GMM_L2_SIZE and initialize L2eIdx?
        {
            pNext = NULL;
        }

        LastLevelTable(GMM_PAGETABLEPool* Elem, int NodeIdx, int DwordL1e, int L2eIndex)
            : LastLevelTable()
        {
            PoolElem = Elem;
            PoolNodeIdx = NodeIdx;
            BBInfo = Elem->GetNodeBBInfoAtIndex(NodeIdx);
            L2eIdx = L2eIndex;
            pNext = NULL;
            UsedEntries = new uint32_t[DwordL1e]();
        }
        ~LastLevelTable()
        {
            delete[] UsedEntries;
        }

        int GetL2eIdx() {
            return L2eIdx;
        }

        LastLevelTable* &Next() {
            return pNext;
        }
    };

    //////////////////////////////////////////////////////////////////////////////////////////////
    /// Contains functions and members for MidLevelTable. 
    /// MidLevelTable defines secondary level tables in multi-level pageTable structure
    /////////////////////////////////////////////////////////////////////////////////////////////
    class MidLevelTable : public Table
    {
    private:
        LastLevelTable  *pTTL1;                    //linked list of L1 tables

    public:
        MidLevelTable() :Table()
        {
            pTTL1 = NULL;
        }
        MidLevelTable(GMM_PAGETABLEPool *Pool, int NodeIdx, SyncInfo Info) : MidLevelTable()
        {
            PoolElem = Pool;
            BBInfo = Info;
            PoolNodeIdx = NodeIdx;
        }
        ~MidLevelTable()
        {
            if (pTTL1)
            {
                LastLevelTable* item = pTTL1;

                while (item)
                {
                    LastLevelTable* nextItem = item->Next();
                    delete item;
                    item = nextItem;
                }

                pTTL1 = NULL;
            }
        }
        LastLevelTable* GetL1Table(GMM_GFX_SIZE_T L2eIdx, LastLevelTable** Prev = NULL)
        {
            LastLevelTable* pL1Tbl = pTTL1;
            LastLevelTable* PrevL1Tbl = NULL;

            while (pL1Tbl)
            {
                if (pL1Tbl->GetL2eIdx() == L2eIdx)
                {
                    break;
                }
                PrevL1Tbl = pL1Tbl;
                pL1Tbl = pL1Tbl->Next();
            }

            //if requested, save previous node in linked-list
            if (Prev)
            {
                *Prev = PrevL1Tbl;
            }
            return pL1Tbl;
        }
        void InsertInList(LastLevelTable* pL1Tbl)
        {
            LastLevelTable* Prev = pTTL1;

            //Insert at end
            while (Prev && Prev->Next())
            {
                Prev = Prev->Next();
            }

            if (Prev)
            {
                Prev->Next() = pL1Tbl;
            }
            else
            {
                pTTL1 = pL1Tbl;
            }
        }
        void DeleteFromList(LastLevelTable* pL1Tbl, LastLevelTable* PrevL1Tbl)
        {
            //Save next L1Table in list, before deleting current one
            if (pL1Tbl)
            {
                if (PrevL1Tbl)
                {
                    PrevL1Tbl->Next() = pL1Tbl->Next();
                }
                else
                {
                    pTTL1 = pL1Tbl->Next();
                }

                delete pL1Tbl;
            }
        }
    };

    /////////////////////////////////////////////////////
    /// Contains functions and members for PageTable. 
    /// PageTable defines multi-level pageTable 
    /////////////////////////////////////////////////////
    class PageTable :
        public GmmMemAllocator
    {
    protected:
        const TT_TYPE TTType;                      //PageTable is AuxTT
        const int NodesPerTable;                   //Aux L2/L3 has 32KB size, Aux L1 has 4KB -can't use as selector for PageTable is AuxTT
                                                   // 1 node for TR-table, 8 nodes for Aux-Table L2, 2 nodes for Aux-table L1
        //Root Table structure
        struct RootTable
        {
            GMM_RESOURCE_INFO* pGmmResInfo;
            HANDLE         L3Handle;
            GMM_GFX_ADDRESS  GfxAddress;              //L3 Table Adr CPU equivalent GPU addr
            GMM_GFX_ADDRESS  CPUAddress;              //LMEM-cpuvisible adr
            bool        NeedRegisterUpdate;        //True @ L3 allocation, False when L3AdrRegWrite done
            SyncInfo        BBInfo;
            RootTable() : pGmmResInfo(NULL), L3Handle(NULL), GfxAddress(0), CPUAddress(0), NeedRegisterUpdate(false), BBInfo() {}
        } TTL3;

        MidLevelTable*   pTTL2;                      //array of L2-Tables

    public:
#ifdef _WIN32
        CRITICAL_SECTION    TTLock;                  //synchronized access of PageTable obj
#elif defined __linux__
        pthread_mutex_t TTLock;
#endif

        GmmPageTableMgr*  PageTableMgr;
        GmmClientContext    *pClientContext;

        PageTable(int Size, int NumL3e, TT_TYPE flag) :
            NodesPerTable(Size / PAGE_SIZE),
            TTType(flag)
        {
            InitializeCriticalSection(&TTLock);

            pTTL2 = new MidLevelTable[NumL3e];
        }

        ~PageTable()
        {
            delete[] pTTL2;

            DeleteCriticalSection(&TTLock);
        }
       
        GMM_GFX_ADDRESS GetL3Address() { return TTL3.GfxAddress; }
        bool &GetRegisterStatus() { return TTL3.NeedRegisterUpdate; }
        GMM_STATUS AllocateL3Table(uint32_t L3TableSize, uint32_t L3AddrAlignment);
        GMM_STATUS DestroyL3Table();
        void AllocateL1L2Table(GMM_GFX_ADDRESS TileAddr, GMM_GFX_ADDRESS * L1TableAdr, GMM_GFX_ADDRESS * L2TableAdr);
        void AllocateDummyTables(GmmLib::Table **L2Table, GmmLib::Table **L1Table);
        void GetL1L2TableAddr(GMM_GFX_ADDRESS TileAddr, GMM_GFX_ADDRESS * L1TableAdr, GMM_GFX_ADDRESS* L2TableAdr);
        uint8_t GetMappingType(GMM_GFX_ADDRESS GfxVA, GMM_GFX_SIZE_T Size, GMM_GFX_ADDRESS& LastAddr);
        HANDLE GetL3Handle() { return TTL3.L3Handle; }
    };

    //////////////////////////////////////////////////////////////////////////////////////////////
    /// Contains functions and members for AuxTable. 
    /// AuxTable defines PageTable for translating VA->AuxVA, ie defines page-walk to get address
    /// of CCS-cacheline containing auxiliary data (compression tag, etc) for some resource
    /////////////////////////////////////////////////////////////////////////////////////////////
    class AuxTable : public PageTable
    {
    public:
        const int L1Size;
        Table* NullL2Table;
        Table* NullL1Table;
        GMM_GFX_ADDRESS NullCCSTile;
        AuxTable() : PageTable(8 * PAGE_SIZE, GMM_AUX_L3_SIZE, TT_TYPE::AUXTT),
            L1Size(2 * PAGE_SIZE)
        {
            NullL2Table = nullptr;
            NullL1Table = nullptr;
            NullCCSTile = 0;
        }
        GMM_STATUS InvalidateTable(GMM_UMD_SYNCCONTEXT * UmdContext, GMM_GFX_ADDRESS BaseAdr, GMM_GFX_SIZE_T Size, uint8_t DoNotWait);

        GMM_STATUS MapValidEntry(GMM_UMD_SYNCCONTEXT *UmdContext, GMM_GFX_ADDRESS BaseAdr, GMM_GFX_SIZE_T BaseSize,
                                 GMM_RESOURCE_INFO* BaseResInfo, GMM_GFX_ADDRESS AuxVA, GMM_RESOURCE_INFO* AuxResInfo, uint64_t PartialData, uint8_t DoNotWait);

        GMM_STATUS MapNullCCS(GMM_UMD_SYNCCONTEXT *UmdContext, GMM_GFX_ADDRESS BaseAdr, GMM_GFX_SIZE_T Size, uint64_t PartialL1e, uint8_t DoNotWait);

        GMM_AUXTTL1e CreateAuxL1Data(GMM_RESOURCE_INFO* BaseResInfo);
        GMM_GFX_ADDRESS GMM_INLINE __GetCCSCacheline(GMM_RESOURCE_INFO* BaseResInfo, GMM_GFX_ADDRESS BaseAdr, GMM_RESOURCE_INFO* AuxResInfo,
                                                     GMM_GFX_ADDRESS AuxVA, GMM_GFX_SIZE_T AdrOffset);

    };

typedef struct _GMM_DEVICE_ALLOC {
    uint32_t            Size;
    uint32_t            Alignment;
    HANDLE              Handle;
    GMM_GFX_ADDRESS     GfxVA;
    GMM_GFX_ADDRESS     CPUVA;
    void *              Priv;
    HANDLE              hCsr;
} GMM_DEVICE_ALLOC;

typedef struct _GMM_DEVICE_DEALLOC {
    HANDLE              Handle;
    GMM_GFX_ADDRESS     GfxVA;
    void *              Priv;
    HANDLE              hCsr;
} GMM_DEVICE_DEALLOC;

GMM_STATUS __GmmDeviceAlloc(GmmClientContext            *pClientContext,
                            GMM_DEVICE_CALLBACKS_INT    *pDeviceCbInt,
                            GMM_DEVICE_ALLOC            *pAlloc);

GMM_STATUS __GmmDeviceDealloc(GMM_CLIENT                ClientType,
                              GMM_DEVICE_CALLBACKS_INT  *DeviceCb,
                              GMM_DEVICE_DEALLOC        *pDealloc);

}
#endif  // #ifdef __cplusplus