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