mirror of https://github.com/intel/gmmlib.git
559 lines
23 KiB
C++
559 lines
23 KiB
C++
/*==============================================================================
|
|
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_USABLESIZE(TTType, pGmmLibContext) (GMM_AUX_L1_USABLESIZE(pGmmLibContext))
|
|
#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)
|
|
#define GMM_L1_ENTRY_IDX_EXPORTED_2(TTType, GfxAddress, WA64KEx, WA16KEx) (GMM_AUX_L1_ENTRY_IDX_EXPORTED_2((GfxAddress), WA64KEx, WA16KEx))
|
|
#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, pGmmLibContext) \
|
|
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 AUX_L1TABLE_SIZE_IN_POOLNODES_2(pGmmLibContext) (pGmmLibContext ? ((WA64K(pGmmLibContext) || WA16K(pGmmLibContext)) ? 2 : 1) : 2) //Aux L1 is 8KB / 4K (MTL)
|
|
#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()
|
|
{
|
|
int DwordPoolSize;
|
|
GMM_LIB_CONTEXT *pGmmLibContext;
|
|
PoolHandle = hAlloc;
|
|
pGmmResInfo = pGmmRes;
|
|
PoolGfxAddress = SysMem;
|
|
CPUAddress = PoolGfxAddress;
|
|
NextPool = NULL;
|
|
NumFreeNodes = PAGETABLE_POOL_MAX_NODES;
|
|
PoolType = Type;
|
|
if(pGmmResInfo)
|
|
{
|
|
pClientContext = pGmmResInfo->GetGmmClientContext();
|
|
}
|
|
pGmmLibContext = pClientContext ? pClientContext->GetLibContext() : NULL;
|
|
DwordPoolSize = (Type == POOL_TYPE_AUXTTL1) ? PAGETABLE_POOL_SIZE_IN_DWORD / AUX_L1TABLE_SIZE_IN_POOLNODES_2(pGmmLibContext) : (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]();
|
|
}
|
|
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)
|
|
{
|
|
GMM_LIB_CONTEXT *pGmmLibContext = pClientContext ? pClientContext->GetLibContext() : NULL;
|
|
int BBInfoNodeIdx = (PoolType == POOL_TYPE_AUXTTL1) ? j / AUX_L1TABLE_SIZE_IN_POOLNODES_2(pGmmLibContext) : (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,GMM_LIB_CONTEXT* pGmmLibContext);
|
|
bool IsTableNullMapped(TT_TYPE Type, bool IsL1, GMM_GFX_ADDRESS TileAdr,GMM_LIB_CONTEXT *pGmmLibContext);
|
|
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) :
|
|
TTType(flag),
|
|
NodesPerTable(Size / PAGE_SIZE)
|
|
{
|
|
PageTableMgr = NULL;
|
|
pClientContext = NULL;
|
|
InitializeCriticalSection(&TTLock);
|
|
|
|
pTTL2 = new MidLevelTable[NumL3e];
|
|
}
|
|
|
|
~PageTable()
|
|
{
|
|
delete[] pTTL2;
|
|
|
|
DeleteCriticalSection(&TTLock);
|
|
}
|
|
|
|
inline GMM_LIB_CONTEXT* GetGmmLibContext()
|
|
{
|
|
return pClientContext->GetLibContext();
|
|
}
|
|
|
|
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(GmmClientContext *pClientContextIn)
|
|
: PageTable(8 * PAGE_SIZE, GMM_AUX_L3_SIZE, TT_TYPE::AUXTT), L1Size((WA16K(pClientContextIn->GetLibContext()) || WA64K(pClientContextIn->GetLibContext())) ? (2 * PAGE_SIZE) : PAGE_SIZE)
|
|
{
|
|
NullL2Table = nullptr;
|
|
NullL1Table = nullptr;
|
|
NullCCSTile = 0;
|
|
}
|
|
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,
|
|
GmmClientContext *pClientContext);
|
|
}
|
|
#endif // #ifdef __cplusplus
|
|
|