Add Pagetable manager  and auxtable  support.

Change-Id: I429b52a70c77fc304c65d28d42b18f99b01116d5
diff --git a/Source/GmmLib/CMakeLists.txt b/Source/GmmLib/CMakeLists.txt
index dbb3d5e..db4373d 100644
--- a/Source/GmmLib/CMakeLists.txt
+++ b/Source/GmmLib/CMakeLists.txt
@@ -191,6 +191,7 @@
 	${BS_DIR_GMMLIB}/inc/External/Common/GmmConst.h
 	${BS_DIR_GMMLIB}/inc/External/Common/GmmDebug.h
 	${BS_DIR_GMMLIB}/inc/External/Common/GmmFormatTable.h
+	${BS_DIR_GMMLIB}/inc/External/Common/GmmHw.h
 	${BS_DIR_GMMLIB}/inc/External/Common/GmmInfo.h
 	${BS_DIR_GMMLIB}/inc/External/Common/GmmInfoExt.h
 	${BS_DIR_GMMLIB}/inc/External/Common/GmmInternal.h
@@ -205,6 +206,7 @@
 	${BS_DIR_GMMLIB}/inc/External/Common/GmmTextureExt.h
 	${BS_DIR_GMMLIB}/inc/External/Common/GmmUtil.h
 	${BS_DIR_GMMLIB}/inc/External/Linux/GmmResourceInfoLin.h
+        ${BS_DIR_GMMLIB}/inc/External/Linux/GmmResourceInfoLinExt.h
 	${BS_DIR_GMMLIB}/inc/Internal/Common/Platform/GmmGen10Platform.h
 	${BS_DIR_GMMLIB}/inc/Internal/Common/Platform/GmmGen11Platform.h
 	${BS_DIR_GMMLIB}/inc/Internal/Common/Platform/GmmGen12Platform.h
@@ -225,6 +227,7 @@
 
 set(UMD_HEADERS
 	${HEADERS_}
+	${BS_DIR_GMMLIB}/inc/External/Common/GmmPageTableMgr.h
 	${BS_DIR_GMMLIB}/inc/External/Common/GmmClientContext.h
         ${BS_DIR_GMMLIB}/inc/External/Common/GmmLibDll.h
         ${BS_DIR_GMMLIB}/inc/External/Common/GmmLibDllName.h
@@ -250,6 +253,7 @@
   ${BS_DIR_GMMLIB}/Resource/GmmResourceInfoCommon.cpp
   ${BS_DIR_GMMLIB}/Resource/GmmResourceInfoCommonEx.cpp
   ${BS_DIR_GMMLIB}/Resource/GmmRestrictions.cpp
+  ${BS_DIR_GMMLIB}/Resource/Linux/GmmResourceInfoLinCWrapper.cpp
   ${BS_DIR_GMMLIB}/Texture/GmmGen7Texture.cpp
   ${BS_DIR_GMMLIB}/Texture/GmmGen8Texture.cpp
   ${BS_DIR_GMMLIB}/Texture/GmmGen9Texture.cpp
@@ -269,6 +273,9 @@
 
 set(UMD_SOURCES
   ${SOURCES_}
+  ${BS_DIR_GMMLIB}/TranslationTable/GmmAuxTable.cpp
+  ${BS_DIR_GMMLIB}/TranslationTable/GmmPageTableMgr.cpp
+  ${BS_DIR_GMMLIB}/TranslationTable/GmmUmdTranslationTable.cpp
   ${BS_DIR_GMMLIB}/GlobalInfo/GmmClientContext.cpp
   ${BS_DIR_GMMLIB}/GlobalInfo/GmmOldApi.cpp
    ${BS_DIR_GMMLIB}/GlobalInfo/GmmLibDllMain.cpp
@@ -287,13 +294,27 @@
 source_group("Source Files\\Global" ${BS_DIR_GMMLIB}/GlobalInfo/.*)
 source_group("Source Files\\Platform" ${BS_DIR_GMMLIB}/Platform/.*)
 source_group("Source Files\\Texture" ${BS_DIR_GMMLIB}/Texture/.*)
+source_group("Source Files\\Translation Table" ${BS_DIR_GMMLIB}/TranslationTable/.*)
 source_group("Source Files\\Utility" ${BS_DIR_GMMLIB}/Utility/.*)
 
 source_group("Source Files\\Resource" FILES
 			${BS_DIR_GMMLIB}/Resource/GmmResourceInfo.cpp
 			${BS_DIR_GMMLIB}/Resource/GmmResourceInfoCommon.cpp
+			${BS_DIR_GMMLIB}/Resource/GmmResourceInfoCommonEx.cpp
 			${BS_DIR_GMMLIB}/Resource/GmmRestrictions.cpp)
 
+source_group("Source Files\\Resource\\Linux" FILES
+			${BS_DIR_GMMLIB}/Resource/Linux/GmmResourceInfoLinCWrapper.cpp
+			)
+
+source_group("Source Files\\TranslationTable\\Windows" FILES
+			 ${BS_DIR_GMMLIB}/TranslationTable/GmmAuxTable.cpp
+			 ${BS_DIR_GMMLIB}/TranslationTable/GmmPageTableMgr.cpp
+			 ${BS_DIR_GMMLIB}/TranslationTable/GmmUmdTranslationTable.cpp)
+
+source_group("Source Files\\TranslationTable" FILES
+			${BS_DIR_GMMLIB}/TranslationTable/GmmUmdTranslationTable.h)
+
 source_group("Header Files\\External\\Common" FILES
 			${BS_DIR_GMMLIB}/inc/External/Common/GmmCachePolicy.h
 			${BS_DIR_GMMLIB}/inc/External/Common/GmmCachePolicyCommon.h
@@ -302,6 +323,7 @@
 			${BS_DIR_GMMLIB}/inc/External/Common/GmmConst.h
 			${BS_DIR_GMMLIB}/inc/External/Common/GmmDebug.h
 			${BS_DIR_GMMLIB}/inc/External/Common/GmmFormatTable.h
+			${BS_DIR_GMMLIB}/inc/External/Common/GmmHw.h
 			${BS_DIR_GMMLIB}/inc/External/Common/GmmInfo.h
 			${BS_DIR_GMMLIB}/inc/External/Common/GmmInfoExt.h
 			${BS_DIR_GMMLIB}/inc/External/Common/GmmInternal.h
@@ -331,6 +353,7 @@
 
 source_group("Header Files\\External\\Linux" FILES
 			 ${BS_DIR_GMMLIB}/inc/External/Linux/GmmResourceInfoLin.h
+			 ${BS_DIR_GMMLIB}/inc/External/Linux/GmmResourceInfoLinExt.h
 			)
 
 source_group("Header Files\\Internal\\Common" FILES
diff --git a/Source/GmmLib/GlobalInfo/GmmClientContext.cpp b/Source/GmmLib/GlobalInfo/GmmClientContext.cpp
index 655f9ff..51258f0 100644
--- a/Source/GmmLib/GlobalInfo/GmmClientContext.cpp
+++ b/Source/GmmLib/GlobalInfo/GmmClientContext.cpp
@@ -27,6 +27,7 @@
 #include "..\..\inc\common\gfxEscape.h"
 #include "..\..\..\miniport\LHDM\inc\gmmEscape.h"
 #include "Internal\Windows\GmmResourceInfoWinInt.h"
+#include "../TranslationTable/GmmUmdTranslationTable.h"
 #endif
 
 /////////////////////////////////////////////////////////////////////////////////////
@@ -465,6 +466,40 @@
     }
 }
 
+/////////////////////////////////////////////////////////////////////////////////////
+/// Member function of ClientContext class for creation of PAgeTableMgr Object .
+/// @see        GmmLib::GMM_PAGETABLE_MGR::GMM_PAGETABLE_MGR
+///
+/// @param[in] pDevCb: Pointer to GMM_DEVICE_CALLBACKS_INT
+/// @param[in] pTTCB: Pointer to GMM_TRANSLATIONTABLE_CALLBACKS
+/// @param[in] TTFags
+/// @return     Pointer to GMM_PAGETABLE_MGR class.
+//TBD: move the code to new overloaded the API and remove this API once all clients are moved to new API.
+/////////////////////////////////////////////////////////////////////////////////////
+GMM_PAGETABLE_MGR* GMM_STDCALL GmmLib::GmmClientContext::CreatePageTblMgrObject(GMM_DEVICE_CALLBACKS_INT* pDevCb,
+                                                                                uint32_t TTFlags)
+{
+    GMM_PAGETABLE_MGR* pPageTableMgr = NULL;
+
+    pPageTableMgr = new GMM_PAGETABLE_MGR(pDevCb, TTFlags, this);
+
+    return pPageTableMgr;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// Member function of ClientContext class for destroy of PageTableMgr Object .
+///
+/// @param[in] pPageTableMgr: Pointer to GMM_PAGETABLE_MGR
+/// @return     void.
+/////////////////////////////////////////////////////////////////////////////////////
+void GMM_STDCALL GmmLib::GmmClientContext::DestroyPageTblMgrObject(GMM_PAGETABLE_MGR* pPageTableMgr)
+{
+    if (pPageTableMgr)
+    {
+        delete pPageTableMgr;
+    }
+}
+
 #ifdef GMM_LIB_DLL
 /////////////////////////////////////////////////////////////////////////////////////
 /// Member function of ClientContext class for creation of ResourceInfo Object .
@@ -568,6 +603,48 @@
     }
 }
 #endif
+/////////////////////////////////////////////////////////////////////////////////////
+/// Member function of ClientContext class for creation of PAgeTableMgr Object .
+/// @see        GmmLib::GMM_PAGETABLE_MGR::GMM_PAGETABLE_MGR
+///
+/// @param[in] pDevCb: Pointer to GMM_DEVICE_CALLBACKS_INT
+/// @param[in] pTTCB: Pointer to GMM_TRANSLATIONTABLE_CALLBACKS
+/// @param[in] TTFags
+/// @return     Pointer to GMM_PAGETABLE_MGR class.
+/// TBD: move the code to new overloaded the API and remove this API once all clients are moved to new API.
+/////////////////////////////////////////////////////////////////////////////////////
+GMM_PAGETABLE_MGR* GMM_STDCALL GmmLib::GmmClientContext::CreatePageTblMgrObject(
+                                                         GMM_DEVICE_CALLBACKS_INT* pDevCb,
+                                                         uint32_t                      TTFlags,
+                                                         GmmClientAllocationCallbacks* pAllocCbs)
+{
+    if (!pAllocCbs || !pAllocCbs->pfnAllocation)
+    {
+        return CreatePageTblMgrObject(
+            pDevCb,
+            TTFlags);
+    }
+    else
+    {
+        GMM_PAGETABLE_MGR* pPageTableMgr = NULL;
+        return pPageTableMgr;
+    }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// Member function of ClientContext class for destroy of PageTableMgr Object .
+///
+/// @param[in] pPageTableMgr: Pointer to GMM_PAGETABLE_MGR
+/// @return     void.
+/////////////////////////////////////////////////////////////////////////////////////
+void GMM_STDCALL GmmLib::GmmClientContext::DestroyPageTblMgrObject(GMM_PAGETABLE_MGR* pPageTableMgr,
+    GmmClientAllocationCallbacks* pAllocCbs)
+{
+    if (!pAllocCbs || !pAllocCbs->pfnFree)
+    {
+        return DestroyPageTblMgrObject(pPageTableMgr);
+    }
+}
 
 /////////////////////////////////////////////////////////////////////////////////////
 /// Gmm lib DLL exported C wrapper for creating GmmLib::GmmClientContext object
diff --git a/Source/GmmLib/Resource/GmmRestrictions.cpp b/Source/GmmLib/Resource/GmmRestrictions.cpp
index 5f591fc..aca889d 100644
--- a/Source/GmmLib/Resource/GmmRestrictions.cpp
+++ b/Source/GmmLib/Resource/GmmRestrictions.cpp
@@ -577,7 +577,7 @@
     if(pTexinfo->Flags.Info.RenderCompressed ||
        pTexinfo->Flags.Info.MediaCompressed)
     {
-        Restrictions.Alignment = GFX_ALIGN(Restrictions.Alignment, GMM_KBYTE(64));
+        Restrictions.Alignment = GFX_ALIGN(Restrictions.Alignment, (!WA16K ? GMM_KBYTE(64) : GMM_KBYTE(16)));
     }
 
     GMM_DPF_EXIT;
diff --git a/Source/GmmLib/Resource/Linux/GmmResourceInfoLinCWrapper.cpp b/Source/GmmLib/Resource/Linux/GmmResourceInfoLinCWrapper.cpp
new file mode 100644
index 0000000..546815f
--- /dev/null
+++ b/Source/GmmLib/Resource/Linux/GmmResourceInfoLinCWrapper.cpp
@@ -0,0 +1,179 @@
+/*==============================================================================
+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.
+============================================================================*/
+
+#include "Internal/Common/GmmLibInc.h"
+
+#if defined(__linux__) && !LHDM
+#include "Internal/Linux/GmmResourceInfoLinInt.h"
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// This is an overloaded function to call DeviceCb Function for CreateAllocation
+///
+/// @param[in]  ClientType
+/// @param[in]  pDeviceCb: Pointer to GMM_DEVICE_CALLBACKS_INT Struct
+/// @param[in]  pAllocate: Pointer to GMM_DDI_ALLOCATE Union
+/// @return     Status of CreateAllocation call.
+/////////////////////////////////////////////////////////////////////////////////////
+int GmmDeviceCallback(GMM_CLIENT ClientType, GMM_DEVICE_CALLBACKS_INT *pDeviceCb, GMM_DDI_ALLOCATE *pAllocate)
+{
+    int      Status   = 0;
+    void *   pBo      = NULL;
+    void *   pCpuAddr = NULL;
+    uint64_t gpuAddr  = 0ULL;
+
+    Status = pDeviceCb->DevCbPtrs_.pfnAllocate(pDeviceCb->pBufMgr,
+                                               pAllocate->size,
+                                               pAllocate->alignment,
+                                               &pBo,
+                                               &pCpuAddr,
+                                               &gpuAddr);
+    pAllocate->bo      = pBo;
+    pAllocate->cpuAddr = pCpuAddr;
+    pAllocate->gfxAddr = gpuAddr;
+
+    return Status;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// This is an overloaded function to call DeviceCb Function for DestroyAllocation
+///
+/// @param[in]  ClientType
+/// @param[in]  pDeviceCb: Pointer to GMM_DEVICE_CALLBACKS_INT Struct
+/// @param[in]  pAllocate: Pointer to GMM_DDI_DEALLOCATE Union
+/// @return     Status of DestroyAllocation call.
+/////////////////////////////////////////////////////////////////////////////////////
+int GmmDeviceCallback(GMM_CLIENT ClientType, GMM_DEVICE_CALLBACKS_INT *pDeviceCb, GMM_DDI_DEALLOCATE *pDeallocate)
+{
+    int Status = 0;
+
+    pDeviceCb->DevCbPtrs_.pfnDeallocate(pDeallocate->bo);
+
+    return Status;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// This is an overloaded function to call DeviceCb Function for WaitForSyncObjFromCpu
+///
+/// @param[in]  ClientType
+/// @param[in]  pDeviceCb: Pointer to GMM_DEVICE_CALLBACKS_INT Struct
+/// @param[in]  pAllocate: Pointer to GMM_DDI_WAITFORSYNCHRONIZATIONOBJECTFROMCPU Union
+/// @return     Status of WaitForSyncObjFromCpu call.
+/////////////////////////////////////////////////////////////////////////////////////
+int GmmDeviceCallback(GMM_CLIENT ClientType, GMM_DEVICE_CALLBACKS_INT *pDeviceCb, GMM_DDI_WAITFORSYNCHRONIZATIONOBJECTFROMCPU *pWait)
+{
+    int Status = 0;
+
+    pDeviceCb->DevCbPtrs_.pfnWaitFromCpu(pWait->bo);
+
+    return Status;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// This function checks for Null DeviceCb Function pointer
+///
+/// @param[in]  ClientType
+/// @param[in]  pDeviceCb: Pointer to GMM_DEVICE_CALLBACKS_INT Struct
+/// @param[in]  CallBackType Enum @GMM_DEVICE_CALLBACKS_TYPE
+/// @return     True if not Null.
+/////////////////////////////////////////////////////////////////////////////////////
+int GmmCheckForNullDevCbPfn(GMM_CLIENT ClientType, GMM_DEVICE_CALLBACKS_INT *pDeviceCb, GMM_DEVICE_CALLBACKS_TYPE CallBackType)
+{
+    int Status = 0;
+
+    switch(CallBackType)
+    {
+        case GMM_DEV_CB_ALLOC:
+            Status = (pDeviceCb->DevCbPtrs_.pfnAllocate != 0);
+            break;
+        case GMM_DEV_CB_DEALLOC:
+            Status = (pDeviceCb->DevCbPtrs_.pfnDeallocate != 0);
+            break;
+        case GMM_DEV_CB_WAIT_FROM_CPU:
+            Status = (pDeviceCb->DevCbPtrs_.pfnWaitFromCpu != 0);
+            break;
+        default:
+            Status = 0;
+            break;
+    }
+
+    return Status;
+}
+
+// Dummy Translation Table Callback for reusing ..
+static inline int DummyPrologTranslationTable(void *pDeviceHandle)
+{
+    return 0;
+}
+
+static inline int DummyWriteL1Entries(void *          pDeviceHandle,
+                                      const uint32_t  NumEntries,
+                                      GMM_GFX_ADDRESS GfxAddress,
+                                      uint32_t *      Data)
+{
+    return 0;
+}
+
+static inline int DummyWriteL2L3Entry(void *          pDeviceHandle,
+                                      GMM_GFX_ADDRESS GfxAddress,
+                                      uint64_t        Data)
+{
+    return 0;
+}
+
+static inline int DummyWriteFenceID(void *          pDeviceHandle,
+                                    GMM_GFX_ADDRESS GfxAddress,
+                                    uint64_t        Data)
+{
+    return 0;
+}
+
+static inline int DummyEpilogTranslationTable(void *  pDeviceHandle,
+                                              uint8_t ForceFlush)
+{
+    return 0;
+}
+
+static inline int DummyCopyL1Entry(void *          pDeviceHandle,
+                                   GMM_GFX_ADDRESS DstGfxAddress,
+                                   GMM_GFX_ADDRESS SrcGfxAddress)
+{
+    return 0;
+}
+
+static inline int DummyWriteL3Adr(void *          pDeviceHandle,
+                                  GMM_GFX_ADDRESS L3GfxAddress,
+                                  uint64_t        RegOffset)
+{
+    return 0;
+}
+
+GMM_TRANSLATIONTABLE_CALLBACKS DummyTTCB = {
+.pfPrologTranslationTable = DummyPrologTranslationTable,
+.pfWriteL1Entries         = DummyWriteL1Entries,
+.pfWriteL2L3Entry         = DummyWriteL2L3Entry,
+.pfWriteFenceID           = DummyWriteFenceID,
+.pfEpilogTranslationTable = DummyEpilogTranslationTable,
+.pfCopyL1Entry            = DummyCopyL1Entry,
+.pfWriteL3Adr             = DummyWriteL3Adr,
+};
+
+#endif /*__linux__*/
diff --git a/Source/GmmLib/Texture/GmmGen11Texture.cpp b/Source/GmmLib/Texture/GmmGen11Texture.cpp
index 63c9986..7e6d60b 100644
--- a/Source/GmmLib/Texture/GmmGen11Texture.cpp
+++ b/Source/GmmLib/Texture/GmmGen11Texture.cpp
@@ -321,9 +321,12 @@
         GMM_GFX_SIZE_T TileHeight = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight;
         GMM_GFX_SIZE_T TileWidth  = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth;
 
-        //U/V must be aligned to AuxT granularity, for 16K AuxT- 4x pitchalign enforces it,
-        //add extra padding for 64K AuxT
-        TileHeight *= 1;
+        if(GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) > IGFX_GEN11LP_CORE)
+        {
+            //U/V must be aligned to AuxT granularity, for 16K AuxT- 4x pitchalign enforces it,
+            //add extra padding for 64K AuxT
+            TileHeight *= (!GMM_IS_64KB_TILE(pTexInfo->Flags) && !WA16K) ? 4 : 1;
+        }
 
         *pUOffsetX = GFX_ALIGN(*pUOffsetX, TileWidth);
         *pUOffsetY = GFX_ALIGN(*pUOffsetY, TileHeight);
diff --git a/Source/GmmLib/Texture/GmmGen12Texture.cpp b/Source/GmmLib/Texture/GmmGen12Texture.cpp
index d6b18a9..450770a 100644
--- a/Source/GmmLib/Texture/GmmGen12Texture.cpp
+++ b/Source/GmmLib/Texture/GmmGen12Texture.cpp
@@ -838,7 +838,7 @@
 
         //U/V must be aligned to AuxT granularity, 4x pitchalign enforces 16K-align,
         //add extra padding for 64K AuxT
-        TileHeight *= (!GMM_IS_64KB_TILE(pTexInfo->Flags)) ? 4 : 1;
+        TileHeight *= (!GMM_IS_64KB_TILE(pTexInfo->Flags) && !WA16K) ? 4 : 1;
 
         if(pTexInfo->Format == GMM_FORMAT_IMC2 || // IMC2, IMC4 needs even tile columns
            pTexInfo->Format == GMM_FORMAT_IMC4)
diff --git a/Source/GmmLib/TranslationTable/GmmAuxTable.cpp b/Source/GmmLib/TranslationTable/GmmAuxTable.cpp
new file mode 100644
index 0000000..4c3d04b
--- /dev/null
+++ b/Source/GmmLib/TranslationTable/GmmAuxTable.cpp
@@ -0,0 +1,949 @@
+/*==============================================================================
+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: AUX-Table management functions 
+             (contains functions to assign memory to 
+			 AUX-Tables with valid entries, 
+			 and update their entries on request)
+
+============================================================================*/
+
+#include "Internal/Common/GmmLibInc.h"
+#include "../TranslationTable/GmmUmdTranslationTable.h"
+
+#if !defined(__GMM_KMD__)
+
+//=============================================================================
+//
+// Function: MapNullCCS
+//
+// Desc: Maps given resource, with dummy null-ccs chain, on Aux Table
+//
+// Caller: UpdateAuxTable (map op for null-tiles)
+//
+// Parameters:
+//      UmdContext: Caller-thread specific info (regarding BB for TR-Aux udpate, cmdQ to use etc)
+//      BaseAdr: Start adr of main surface
+//      Size:   Main-surface size in bytes
+//      PartialL1e: Aux-metadata other than AuxVA
+//      DoNotWait: 1 for CPU update, 0 for async(Gpu) update
+//-----------------------------------------------------------------------------
+GMM_STATUS GmmLib::AuxTable::MapNullCCS(GMM_UMD_SYNCCONTEXT *UmdContext, GMM_GFX_ADDRESS BaseAdr, GMM_GFX_SIZE_T Size, uint64_t PartialL1e, uint8_t DoNotWait)
+{
+    GMM_STATUS      Status       = GMM_SUCCESS;
+    GMM_GFX_SIZE_T  L1TableSize  = (GMM_L1_SIZE(AUXTT, pGmmGlobalContext)) * (!WA16K ? GMM_KBYTE(64) : GMM_KBYTE(16)); //Each AuxTable entry maps 16K main-surface
+    GMM_GFX_ADDRESS Addr         = 0;
+    GMM_GFX_ADDRESS L3GfxAddress = 0;
+    GMM_CLIENT      ClientType;
+
+    GET_GMM_CLIENT_TYPE(pClientContext, ClientType);
+
+    EnterCriticalSection(&TTLock);
+
+    DoNotWait |= (!UmdContext || !UmdContext->pCommandQueueHandle);
+
+    if(TTL3.L3Handle)
+    {
+        L3GfxAddress = TTL3.GfxAddress;
+    }
+    else
+    {
+        LeaveCriticalSection(&TTLock);
+        return GMM_ERROR;
+    }
+
+    if(!DoNotWait)
+    {
+        PageTableMgr->TTCb.pfPrologTranslationTable(
+        UmdContext->pCommandQueueHandle);
+    }
+
+    // For each L1 table
+    for(Addr = GFX_ALIGN_FLOOR(BaseAdr, L1TableSize); // Start at begining of L1 table
+        Addr < BaseAdr + Size;
+        Addr += L1TableSize) // Increment by 1 L1 table
+    {
+        GMM_GFX_ADDRESS L1GfxAddress, L2GfxAddress;
+        GMM_GFX_ADDRESS L1CPUAddress, L2CPUAddress;
+        GMM_GFX_ADDRESS StartAddress = 0;
+        GMM_GFX_ADDRESS EndAddress   = 0;
+        GMM_GFX_ADDRESS TileAddr     = 0;
+        GMM_GFX_SIZE_T  L2eIdx       = 0;
+
+        StartAddress = Addr < BaseAdr ? BaseAdr : Addr;
+        EndAddress   = Addr + L1TableSize;
+        if(EndAddress > BaseAdr + Size)
+        {
+            EndAddress = BaseAdr + Size;
+        }
+
+        GetL1L2TableAddr(StartAddress,
+                         &L1GfxAddress,
+                         &L2GfxAddress);
+
+        // If tables are not there, then they are already invalidated as part of
+        // AUX-TT initialization or other APIs.
+        if(L2GfxAddress == GMM_NO_TABLE ||
+           L1GfxAddress == GMM_NO_TABLE)
+        {
+            //Clear Valid-bit for L3Entry or L2Entry
+            uint64_t        Data            = 0;
+            GMM_GFX_ADDRESS TableGfxAddress = (L2GfxAddress == GMM_NO_TABLE) ? L3GfxAddress : L2GfxAddress;
+            GMM_GFX_ADDRESS TableCPUAddress = (L2GfxAddress == GMM_NO_TABLE) ? TTL3.CPUAddress : pTTL2[GMM_L3_ENTRY_IDX(AUXTT, StartAddress)].GetCPUAddress();
+            uint32_t        TableEntryIdx   = (L2GfxAddress == GMM_NO_TABLE) ? static_cast<uint32_t>(GMM_L3_ENTRY_IDX(AUXTT, StartAddress)) : static_cast<uint32_t>(GMM_L2_ENTRY_IDX(AUXTT, StartAddress));
+            L2CPUAddress                    = (L2GfxAddress == GMM_NO_TABLE) ? 0 : TableCPUAddress;
+
+            if(!NullL1Table || !NullL2Table)
+            {
+                AllocateDummyTables(&NullL2Table, &NullL1Table);
+                if(!NullL1Table || !NullL2Table)
+                {
+                    //report error
+                    LeaveCriticalSection(&TTLock);
+                    return GMM_OUT_OF_MEMORY;
+                }
+                else
+                {
+                    //Initialize dummy table entries (one-time)
+                    GMM_GFX_ADDRESS TableAddr = NullL2Table->GetCPUAddress();
+                    GMM_AUXTTL2e    L2e       = {0};
+                    L2e.Valid                 = 1;
+                    L2e.L1GfxAddr             = (NullL1Table->GetPool()->GetGfxAddress() + PAGE_SIZE * NullL1Table->GetNodeIdx()) >> 13;
+                    for(int i = 0; i < GMM_AUX_L2_SIZE; i++)
+                    {
+                        //initialize L2e ie clear Valid bit for all entries
+                        ((GMM_AUXTTL2e *)TableAddr)[i].Value = L2e.Value;
+                    }
+
+                    TableAddr = NullL1Table->GetCPUAddress();
+
+                    GMM_AUXTTL1e L1e = {0};
+                    L1e.Valid        = 1;
+                    L1e.GfxAddress   = (NullCCSTile >> 8);
+                    for(int i = 0; i < GMM_AUX_L1_SIZE(pGmmGlobalContext); i++)
+                    {
+                        //initialize L1e with null ccs tile
+                        ((GMM_AUXTTL1e *)TableAddr)[i].Value = L1e.Value;
+                    }
+                }
+            }
+
+            if(L2GfxAddress == GMM_NO_TABLE)
+            {
+                GMM_AUXTTL3e L3e = {0};
+                L3e.Valid        = 1;
+                L3e.L2GfxAddr    = (NullL2Table->GetPool()->GetGfxAddress() + PAGE_SIZE * NullL2Table->GetNodeIdx()) >> 15;
+                Data             = L3e.Value;
+            }
+            else
+            {
+                GMM_AUXTTL2e L2e = {0};
+                L2e.Valid        = 1;
+                L2e.L1GfxAddr    = (NullL1Table->GetPool()->GetGfxAddress() + PAGE_SIZE * NullL1Table->GetNodeIdx()) >> 13;
+                Data             = L2e.Value;
+            }
+
+            if(DoNotWait)
+            {
+                //Sync update on CPU
+                ((GMM_AUXTTL2e *)TableCPUAddress)[TableEntryIdx].Value = Data;
+            }
+            else
+            {
+                if(L2GfxAddress != GMM_NO_TABLE)
+                {
+                    pTTL2[GMM_L3_ENTRY_IDX(AUXTT, StartAddress)].UpdatePoolFence(UmdContext, false);
+                }
+                PageTableMgr->TTCb.pfWriteL2L3Entry(UmdContext->pCommandQueueHandle,
+                                                    TableGfxAddress + TableEntryIdx * GMM_AUX_L2e_SIZE,
+                                                    Data);
+            }
+            continue;
+        }
+        else
+        {
+            uint32_t L3eIdx = static_cast<uint32_t>(GMM_L3_ENTRY_IDX(AUXTT, StartAddress));
+            L2CPUAddress    = pTTL2[L3eIdx].GetCPUAddress();
+
+            L2eIdx = GMM_L2_ENTRY_IDX(AUXTT, StartAddress);
+            if(DoNotWait)
+            {
+                //Sync update on CPU
+                ((GMM_AUXTTL3e *)(TTL3.CPUAddress))[L3eIdx].Valid     = 1; //set Valid bit
+                ((GMM_AUXTTL3e *)(TTL3.CPUAddress))[L3eIdx].L2GfxAddr = L2GfxAddress >> 15;
+
+                ((GMM_AUXTTL2e *)L2CPUAddress)[L2eIdx].Valid     = 1; //set Valid bit
+                ((GMM_AUXTTL2e *)L2CPUAddress)[L2eIdx].L1GfxAddr = L1GfxAddress >> 13;
+            }
+            else
+            {
+                GMM_AUXTTL3e L3e = {0};
+                L3e.Valid        = 1;
+                L3e.L2GfxAddr    = L2GfxAddress >> 15;
+                PageTableMgr->TTCb.pfWriteL2L3Entry(
+                UmdContext->pCommandQueueHandle,
+                L3GfxAddress + (L3eIdx * GMM_AUX_L3e_SIZE),
+                L3e.Value);
+
+                pTTL2[L3eIdx].UpdatePoolFence(UmdContext, false);
+
+                GMM_AUXTTL2e L2e = {0};
+                L2e.Valid        = 1;
+                L2e.L1GfxAddr    = L1GfxAddress >> 13;
+                PageTableMgr->TTCb.pfWriteL2L3Entry(
+                UmdContext->pCommandQueueHandle,
+                L2GfxAddress + (L2eIdx * GMM_AUX_L2e_SIZE),
+                L2e.Value);
+            }
+        }
+
+        // For each 64KB or 16KB of main surface (entry) in L1 table
+        for(TileAddr = StartAddress;
+            TileAddr < EndAddress;
+            TileAddr += (!WA16K ? GMM_KBYTE(64) : GMM_KBYTE(16)))
+        {
+            uint64_t                Data   = PartialL1e | NullCCSTile | __BIT(0);
+            GMM_GFX_SIZE_T          L1eIdx = GMM_L1_ENTRY_IDX(AUXTT, TileAddr, pGmmGlobalContext);
+            GmmLib::LastLevelTable *pL1Tbl = NULL;
+
+            pL1Tbl       = pTTL2[GMM_AUX_L3_ENTRY_IDX(TileAddr)].GetL1Table(L2eIdx, NULL);
+            L1CPUAddress = pL1Tbl->GetCPUAddress();
+            if(DoNotWait)
+            {
+                //Sync update on CPU
+                ((GMM_AUXTTL1e *)L1CPUAddress)[L1eIdx].Value = Data;
+
+                GMM_DPF(GFXDBG_CRITICAL, "Null-Map | Table Entry: [0x%06x] L2Addr[0x%016llX] Value[0x%016llX] :: [0x%06x] L1Addr[0x%016llX] Value[0x%016llX]\n", L2eIdx, ((GMM_AUXTTL2e *)L2CPUAddress)[L2eIdx], ((GMM_AUXTTL2e *)L2CPUAddress)[L2eIdx].L1GfxAddr << 13, L1eIdx, &((GMM_AUXTTL1e *)L1CPUAddress)[L1eIdx], Data);
+            }
+            else
+            {
+                pL1Tbl->UpdatePoolFence(UmdContext, false);
+
+                /*                PageTableMgr->TTCb.pfWriteL1Entries(
+                    UmdContext->pCommandQueueHandle,
+                    2,
+                    L1GfxAddress + (L1eIdx * GMM_AUX_L1e_SIZE),
+                    (uint32_t*)(&Data));*/ //**********REQUIRE UMD CHANGE TO UPDATE 64-bit ENTRY - both DWORDs must be updated atomically*******/
+                PageTableMgr->TTCb.pfWriteL2L3Entry(
+                UmdContext->pCommandQueueHandle,
+                L1GfxAddress + (L1eIdx * GMM_AUX_L1e_SIZE),
+                Data);
+            }
+
+            if(pL1Tbl->TrackTableUsage(AUXTT, true, TileAddr, true))
+            { // L1 Table is not being used anymore
+                GMM_AUXTTL2e               L2e      = {0};
+                GmmLib::GMM_PAGETABLEPool *PoolElem = NULL;
+                GmmLib::LastLevelTable *   pL1Tbl = NULL, *Prev = NULL;
+
+                pL1Tbl = pTTL2[GMM_L3_ENTRY_IDX(AUXTT, TileAddr)].GetL1Table(L2eIdx, &Prev);
+                // Map L2-entry to Null-L1Table
+                L2e.Valid     = 1;
+                L2e.L1GfxAddr = (NullL1Table->GetPool()->GetGfxAddress() + PAGE_SIZE * NullL1Table->GetNodeIdx()) >> 13;
+                if(DoNotWait)
+                {
+                    //Sync update on CPU
+                    ((GMM_AUXTTL2e *)L2CPUAddress)[L2eIdx].Value = L2e.Value;
+                }
+                else
+                {
+                    pTTL2[GMM_L3_ENTRY_IDX(AUXTT, TileAddr)].UpdatePoolFence(UmdContext, false);
+                    PageTableMgr->TTCb.pfWriteL2L3Entry(UmdContext->pCommandQueueHandle,
+                                                        L2GfxAddress + L2eIdx * GMM_AUX_L2e_SIZE,
+                                                        L2e.Value);
+                }
+                //Update usage for PoolNode assigned to L1Table, and free L1Tbl
+                if(pL1Tbl)
+                {
+                    PoolElem = pL1Tbl->GetPool();
+                    if(PoolElem)
+                    {
+                        if(pL1Tbl->GetBBInfo().BBQueueHandle)
+                        {
+                            PoolElem->GetNodeBBInfoAtIndex(pL1Tbl->GetNodeIdx()) = pL1Tbl->GetBBInfo();
+                        }
+                        DEASSIGN_POOLNODE(PageTableMgr, UmdContext, PoolElem, pL1Tbl->GetNodeIdx(), AUX_L1TABLE_SIZE_IN_POOLNODES)
+                    }
+                    pTTL2[GMM_L3_ENTRY_IDX(AUXTT, TileAddr)].DeleteFromList(pL1Tbl, Prev);
+                }
+
+                // The L1 table is unused -- meaning everything else in this table is
+                // already invalid. So, break early.
+                break;
+            }
+        }
+    }
+
+    if(!DoNotWait)
+    {
+        PageTableMgr->TTCb.pfEpilogTranslationTable(
+        UmdContext->pCommandQueueHandle,
+        1); // ForceFlush
+    }
+    LeaveCriticalSection(&TTLock);
+
+    return Status;
+}
+
+//=============================================================================
+//
+// Function: InvalidateTable (InvalidateMappings)
+//
+// Desc: Unmaps given resource from Aux Table; and marks affected entries as invalid
+//
+// Caller: UpdateAuxTable (unmap op)
+//
+// Parameters:
+//      UmdContext: Caller-thread specific info (regarding BB for Aux udpate, cmdQ to use etc)
+//      BaseAdr: Start adr of main surface
+//      Size:   Main-surface size in bytes? (or take GmmResInfo?)
+//      DoNotWait: 1 for CPU update, 0 for async(Gpu) update
+//-----------------------------------------------------------------------------
+GMM_STATUS GmmLib::AuxTable::InvalidateTable(GMM_UMD_SYNCCONTEXT *UmdContext, GMM_GFX_ADDRESS BaseAdr, GMM_GFX_SIZE_T Size, uint8_t DoNotWait)
+{
+    GMM_STATUS      Status       = GMM_SUCCESS;
+    GMM_GFX_SIZE_T  L1TableSize  = (GMM_L1_SIZE(AUXTT, pGmmGlobalContext)) * (!WA16K ? GMM_KBYTE(64) : GMM_KBYTE(16)); //Each AuxTable entry maps 16K main-surface
+    GMM_GFX_ADDRESS Addr         = 0;
+    GMM_GFX_ADDRESS L3GfxAddress = 0;
+    uint8_t         isTRVA       = 0; 
+
+    GMM_CLIENT ClientType;
+
+    GET_GMM_CLIENT_TYPE(pClientContext, ClientType);
+
+    //NullCCSTile isn't initialized, disable TRVA path
+    isTRVA = (NullCCSTile ? isTRVA : 0);
+
+    EnterCriticalSection(&TTLock);
+
+    DoNotWait |= (!UmdContext || !UmdContext->pCommandQueueHandle);
+
+    if(TTL3.L3Handle)
+    {
+        L3GfxAddress = TTL3.GfxAddress;
+    }
+    else
+    {
+        LeaveCriticalSection(&TTLock);
+        return GMM_ERROR;
+    }
+
+    if(!DoNotWait)
+    {
+        PageTableMgr->TTCb.pfPrologTranslationTable(
+        UmdContext->pCommandQueueHandle);
+    }
+
+    // For each L1 table
+    for(Addr = GFX_ALIGN_FLOOR(BaseAdr, L1TableSize); // Start at begining of L1 table
+        Addr < BaseAdr + Size;
+        Addr += L1TableSize) // Increment by 1 L1 table
+    {
+        GMM_GFX_ADDRESS L1GfxAddress, L2GfxAddress;
+        GMM_GFX_ADDRESS L1CPUAddress, L2CPUAddress;
+        GMM_GFX_ADDRESS StartAddress = 0;
+        GMM_GFX_ADDRESS EndAddress   = 0;
+        GMM_GFX_ADDRESS TileAddr     = 0;
+        GMM_GFX_SIZE_T  L2eIdx       = 0;
+
+        StartAddress = Addr < BaseAdr ? BaseAdr : Addr;
+        EndAddress   = Addr + L1TableSize;
+        if(EndAddress > BaseAdr + Size)
+        {
+            EndAddress = BaseAdr + Size;
+        }
+
+        GetL1L2TableAddr(StartAddress,
+                         &L1GfxAddress,
+                         &L2GfxAddress);
+
+        // If tables are not there, then they are already invalidated as part of
+        // AUX-TT initialization or other APIs.
+        if(L2GfxAddress == GMM_NO_TABLE ||
+           L1GfxAddress == GMM_NO_TABLE)
+        {
+            //Clear Valid-bit for L3Entry or L2Entry
+            GMM_AUXTTL2e    L2e             = {0}; //AUXTT L3e is identical to L2e, reuse.
+            GMM_GFX_ADDRESS TableGfxAddress = (L2GfxAddress == GMM_NO_TABLE) ? L3GfxAddress : L2GfxAddress;
+            GMM_GFX_ADDRESS TableCPUAddress = (L2GfxAddress == GMM_NO_TABLE) ? TTL3.CPUAddress : pTTL2[GMM_L3_ENTRY_IDX(AUXTT, StartAddress)].GetCPUAddress();
+            uint32_t        TableEntryIdx   = (L2GfxAddress == GMM_NO_TABLE) ? static_cast<uint32_t>(GMM_L3_ENTRY_IDX(AUXTT, StartAddress)) : static_cast<uint32_t>(GMM_L2_ENTRY_IDX(AUXTT, StartAddress));
+            L2CPUAddress                    = (L2GfxAddress == GMM_NO_TABLE) ? 0 : TableCPUAddress;
+
+            if(isTRVA && NullL2Table && NullL1Table)
+            {
+                //invalidate if request spans entire stretch ie TileAdr aligns L1TableSize*GMM_L2_SIZE
+                uint64_t Data = 0;
+                if(L2GfxAddress == GMM_NO_TABLE)
+                {
+                    GMM_AUXTTL3e L3e = {0};
+                    L3e.Valid        = 1;
+                    L3e.L2GfxAddr    = (NullL2Table->GetPool()->GetGfxAddress() + PAGE_SIZE * NullL2Table->GetNodeIdx()) >> 15;
+                    Data             = L3e.Value;
+                }
+                else
+                {
+                    GMM_AUXTTL2e L2e = {0};
+                    L2e.Valid        = 1;
+                    L2e.L1GfxAddr    = (NullL1Table->GetPool()->GetGfxAddress() + PAGE_SIZE * NullL1Table->GetNodeIdx()) >> 13;
+                    Data             = L2e.Value;
+                }
+                L2e.Value = Data;
+            }
+            else
+            {
+                L2e.Valid = 0;
+            }
+            if(DoNotWait)
+            {
+                //Sync update on CPU
+                ((GMM_AUXTTL2e *)TableCPUAddress)[TableEntryIdx].Value = L2e.Value;
+            }
+            else
+            {
+                if(L2GfxAddress != GMM_NO_TABLE)
+                {
+                    pTTL2[GMM_L3_ENTRY_IDX(AUXTT, StartAddress)].UpdatePoolFence(UmdContext, false);
+                }
+                PageTableMgr->TTCb.pfWriteL2L3Entry(UmdContext->pCommandQueueHandle,
+                                                    TableGfxAddress + TableEntryIdx * GMM_AUX_L2e_SIZE,
+                                                    L2e.Value);
+            }
+            continue;
+        }
+        else
+        {
+            uint32_t L3eIdx = static_cast<uint32_t>(GMM_L3_ENTRY_IDX(AUXTT, StartAddress));
+            L2CPUAddress    = pTTL2[L3eIdx].GetCPUAddress();
+
+            L2eIdx = GMM_L2_ENTRY_IDX(AUXTT, StartAddress);
+            if(DoNotWait)
+            {
+                //Sync update on CPU
+                ((GMM_AUXTTL3e *)(TTL3.CPUAddress))[L3eIdx].Valid     = 1; //set Valid bit
+                ((GMM_AUXTTL3e *)(TTL3.CPUAddress))[L3eIdx].L2GfxAddr = L2GfxAddress >> 15;
+
+                ((GMM_AUXTTL2e *)L2CPUAddress)[L2eIdx].Valid     = 1; //set Valid bit
+                ((GMM_AUXTTL2e *)L2CPUAddress)[L2eIdx].L1GfxAddr = L1GfxAddress >> 13;
+            }
+            else
+            {
+                GMM_AUXTTL3e L3e = {0};
+                L3e.Valid        = 1;
+                L3e.L2GfxAddr    = L2GfxAddress >> 15;
+                PageTableMgr->TTCb.pfWriteL2L3Entry(
+                UmdContext->pCommandQueueHandle,
+                L3GfxAddress + (L3eIdx * GMM_AUX_L3e_SIZE),
+                L3e.Value);
+
+                pTTL2[L3eIdx].UpdatePoolFence(UmdContext, false);
+
+                GMM_AUXTTL2e L2e = {0};
+                L2e.Valid        = 1;
+                L2e.L1GfxAddr    = L1GfxAddress >> 13;
+                PageTableMgr->TTCb.pfWriteL2L3Entry(
+                UmdContext->pCommandQueueHandle,
+                L2GfxAddress + (L2eIdx * GMM_AUX_L2e_SIZE),
+                L2e.Value);
+            }
+        }
+
+        // For each 64KB or 16KB of main surface (entry) in L1 table
+        for(TileAddr = StartAddress;
+            TileAddr < EndAddress;
+            TileAddr += (!WA16K ? GMM_KBYTE(64) : GMM_KBYTE(16)))
+        {
+            //Invalidation of requested range irrespective of TRVA
+            uint64_t                Data   = GMM_INVALID_AUX_ENTRY;
+            GMM_GFX_SIZE_T          L1eIdx = GMM_L1_ENTRY_IDX(AUXTT, TileAddr, pGmmGlobalContext);
+            GmmLib::LastLevelTable *pL1Tbl = NULL;
+
+            pL1Tbl       = pTTL2[GMM_AUX_L3_ENTRY_IDX(TileAddr)].GetL1Table(L2eIdx, NULL);
+            L1CPUAddress = pL1Tbl->GetCPUAddress();
+            if(DoNotWait)
+            {
+                //Sync update on CPU
+                ((GMM_AUXTTL1e *)L1CPUAddress)[L1eIdx].Value = Data;
+
+                GMM_DPF(GFXDBG_CRITICAL, "UnMap | Table Entry: [0x%06x] L2Addr[0x%016llX] Value[0x%016llX] :: [0x%06x] L1Addr[0x%016llX] Value[0x%016llX]\n", L2eIdx, ((GMM_AUXTTL2e *)L2CPUAddress)[L2eIdx], ((GMM_AUXTTL2e *)L2CPUAddress)[L2eIdx].L1GfxAddr << 13, L1eIdx, &((GMM_AUXTTL1e *)L1CPUAddress)[L1eIdx], Data);
+            }
+            else
+            {
+                pL1Tbl->UpdatePoolFence(UmdContext, false);
+
+                /*                PageTableMgr->TTCb.pfWriteL1Entries(
+                    UmdContext->pCommandQueueHandle,
+                    2,
+                    L1GfxAddress + (L1eIdx * GMM_AUX_L1e_SIZE),
+                    (uint32_t*)(&Data));*/ //**********REQUIRE UMD CHANGE TO UPDATE 64-bit ENTRY - both DWORDs must be updated atomically*******/
+                PageTableMgr->TTCb.pfWriteL2L3Entry(
+                UmdContext->pCommandQueueHandle,
+                L1GfxAddress + (L1eIdx * GMM_AUX_L1e_SIZE),
+                Data);
+            }
+
+            if(pL1Tbl->TrackTableUsage(AUXTT, true, TileAddr, true))
+            { // L1 Table is not being used anymore
+                GMM_AUXTTL2e               L2e      = {0};
+                GmmLib::GMM_PAGETABLEPool *PoolElem = NULL;
+                GmmLib::LastLevelTable *   pL1Tbl = NULL, *Prev = NULL;
+
+                pL1Tbl = pTTL2[GMM_L3_ENTRY_IDX(AUXTT, TileAddr)].GetL1Table(L2eIdx, &Prev);
+
+                if(isTRVA && NullL1Table &&
+                   ((TileAddr > GFX_ALIGN_FLOOR(BaseAdr, L1TableSize) && TileAddr < GFX_ALIGN_NP2(BaseAdr, L1TableSize)) ||
+                    (TileAddr > GFX_ALIGN_FLOOR(BaseAdr + Size, L1TableSize) && TileAddr < GFX_ALIGN_NP2(BaseAdr + Size, L1TableSize))))
+                {
+                    //Invalidation affects entries out of requested range, null-map for TR
+                    L2e.Valid     = 1;
+                    L2e.L1GfxAddr = (NullL1Table->GetPool()->GetGfxAddress() + PAGE_SIZE * NullL1Table->GetNodeIdx()) >> 13;
+                }
+                else
+                {
+                    // Clear valid bit of L2 entry
+                    L2e.Valid                                    = 0;
+                    ((GMM_AUXTTL2e *)L2GfxAddress)[L2eIdx].Valid = 0;
+                }
+                if(DoNotWait)
+                {
+                    //Sync update on CPU
+                    ((GMM_AUXTTL2e *)L2CPUAddress)[L2eIdx].Value = L2e.Value;
+                }
+                else
+                {
+                    pTTL2[GMM_L3_ENTRY_IDX(AUXTT, TileAddr)].UpdatePoolFence(UmdContext, false);
+                    PageTableMgr->TTCb.pfWriteL2L3Entry(UmdContext->pCommandQueueHandle,
+                                                        L2GfxAddress + L2eIdx * GMM_AUX_L2e_SIZE,
+                                                        L2e.Value);
+                }
+                //Update usage for PoolNode assigned to L1Table, and free L1Tbl
+                if(pL1Tbl)
+                {
+                    PoolElem = pL1Tbl->GetPool();
+                    if(PoolElem)
+                    {
+                        if(pL1Tbl->GetBBInfo().BBQueueHandle)
+                        {
+                            PoolElem->GetNodeBBInfoAtIndex(pL1Tbl->GetNodeIdx()) = pL1Tbl->GetBBInfo();
+                        }
+                        DEASSIGN_POOLNODE(PageTableMgr, UmdContext, PoolElem, pL1Tbl->GetNodeIdx(), AUX_L1TABLE_SIZE_IN_POOLNODES)
+                    }
+                    pTTL2[GMM_L3_ENTRY_IDX(AUXTT, TileAddr)].DeleteFromList(pL1Tbl, Prev);
+                }
+
+                // The L1 table is unused -- meaning everything else in this table is
+                // already invalid. So, break early.
+                break;
+            }
+        }
+    }
+
+    if(!DoNotWait)
+    {
+        PageTableMgr->TTCb.pfEpilogTranslationTable(
+        UmdContext->pCommandQueueHandle,
+        1); // ForceFlush
+    }
+
+    LeaveCriticalSection(&TTLock);
+
+    return Status;
+}
+
+//=============================================================================
+//
+// Function: MapValidEntry
+//
+// Desc: Maps given main-surface, on Aux-Table, to get the exact CCS cacheline tied to
+//       different 4x4K pages of main-surface
+//
+// Caller: UpdateAuxTable (map op)
+//
+// Parameters:
+//      UmdContext: ptr to thread-data
+//      BaseAdr: Start adr of main-surface
+//      BaseSize:   main-surface Size in bytes
+//      BaseResInfo: main surface ResInfo
+//      AuxVA: Start adr of Aux-surface
+//      AuxResInfo: Aux surface ResInfo
+//      PartialData: Aux L1 partial data (ie w/o address)
+//      DoNotWait: true for CPU update, false for async(Gpu) update
+//-----------------------------------------------------------------------------
+GMM_STATUS GmmLib::AuxTable::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      Status = GMM_SUCCESS;
+    GMM_GFX_ADDRESS Addr = 0, L3TableAdr = GMM_NO_TABLE;
+    GMM_GFX_SIZE_T  L1TableSize = GMM_AUX_L1_SIZE(pGmmGlobalContext) * (!WA16K ? GMM_KBYTE(64) : GMM_KBYTE(16));
+    GMM_GFX_SIZE_T  CCS$Adr     = AuxVA;
+    uint8_t         isTRVA    =0  ;
+
+    GMM_CLIENT ClientType;
+
+    GET_GMM_CLIENT_TYPE(pClientContext, ClientType);
+
+    //NullCCSTile isn't initialized, disable TRVA path
+    isTRVA = (NullCCSTile ? isTRVA : 0);
+
+    EnterCriticalSection(&TTLock);
+    if(!TTL3.L3Handle || (!DoNotWait && !UmdContext))
+    {
+        Status = GMM_ERROR;
+    }
+    else
+    {
+        L3TableAdr = TTL3.GfxAddress;
+
+        if(!DoNotWait)
+        {
+            PageTableMgr->TTCb.pfPrologTranslationTable(UmdContext->pCommandQueueHandle);
+        }
+
+        GMM_DPF(GFXDBG_CRITICAL, "Mapping surface: GPUVA=0x%016llX Size=0x%08X Aux_GPUVA=0x%016llX\n", BaseAdr, BaseSize, AuxVA);
+        for(Addr = GFX_ALIGN_FLOOR(BaseAdr, L1TableSize); Addr < BaseAdr + BaseSize; Addr += L1TableSize)
+        {
+            GMM_GFX_ADDRESS StartAdr, EndAdr, TileAdr;
+            GMM_GFX_ADDRESS L1TableAdr = GMM_NO_TABLE, L2TableAdr = GMM_NO_TABLE;
+            GMM_GFX_ADDRESS L1TableCPUAdr = GMM_NO_TABLE, L2TableCPUAdr = GMM_NO_TABLE;
+            GMM_GFX_SIZE_T  L2eIdx     = 0;
+            GMM_GFX_SIZE_T  L3eIdx     = 0;
+            bool            AllocateL1 = false, AllocateL2 = false;
+
+            EndAdr   = Addr + L1TableSize;
+            EndAdr   = EndAdr > BaseAdr + BaseSize ? BaseAdr + BaseSize : EndAdr;
+            StartAdr = Addr < BaseAdr ? BaseAdr : Addr;
+
+            L2eIdx = GMM_L2_ENTRY_IDX(AUXTT, StartAdr);
+            L3eIdx = GMM_L3_ENTRY_IDX(AUXTT, StartAdr);
+
+            //Allocate L2/L1 Table -- get L2 Table Adr for <StartAdr,EndAdr>
+            GetL1L2TableAddr(Addr, &L1TableAdr, &L2TableAdr);
+            if(L2TableAdr == GMM_NO_TABLE || L1TableAdr == GMM_NO_TABLE)
+            {
+                AllocateL1 = GMM_NO_TABLE == L1TableAdr;
+                AllocateL2 = GMM_NO_TABLE == L2TableAdr;
+                AllocateL1L2Table(Addr, &L1TableAdr, &L2TableAdr);
+
+                if(L2TableAdr == GMM_NO_TABLE || L1TableAdr == GMM_NO_TABLE)
+                {
+                    LeaveCriticalSection(&TTLock);
+                    return GMM_OUT_OF_MEMORY;
+                }
+
+                if(AllocateL2)
+                {
+                    uint32_t     i = 0;
+                    GMM_AUXTTL2e InvalidEntry;
+                    InvalidEntry.Value = 0;
+                    if(isTRVA && NullL1Table)
+                    {
+                        InvalidEntry.Valid     = 1;
+                        InvalidEntry.L1GfxAddr = (NullL1Table->GetPool()->GetGfxAddress() + PAGE_SIZE * NullL1Table->GetNodeIdx()) >> 13;
+                    }
+
+                    if(DoNotWait)
+                    {
+                        L2TableCPUAdr = pTTL2[L3eIdx].GetCPUAddress();
+
+                        ((GMM_AUXTTL3e *)(TTL3.CPUAddress))[L3eIdx].Value     = 0;
+                        ((GMM_AUXTTL3e *)(TTL3.CPUAddress))[L3eIdx].L2GfxAddr = L2TableAdr >> 15;
+                        ((GMM_AUXTTL3e *)(TTL3.CPUAddress))[L3eIdx].Valid     = 1;
+                        for(i = 0; i < GMM_AUX_L2_SIZE; i++)
+                        {
+                            //initialize L2e ie clear Valid bit for all entries
+                            ((GMM_AUXTTL2e *)L2TableCPUAdr)[i].Value = InvalidEntry.Value;
+                        }
+                    }
+                    else
+                    {
+                        GMM_AUXTTL3e L3e = {0};
+                        L3e.Valid        = 1;
+                        L3e.L2GfxAddr    = L2TableAdr >> 15;
+                        PageTableMgr->TTCb.pfWriteL2L3Entry(UmdContext->pCommandQueueHandle,
+                                                            L3TableAdr + L3eIdx * GMM_AUX_L3e_SIZE,
+                                                            L3e.Value);
+
+                        //initialize L2e ie clear valid bit for all entries
+                        for(i = 0; i < GMM_AUX_L2_SIZE; i++)
+                        {
+                            PageTableMgr->TTCb.pfWriteL2L3Entry(UmdContext->pCommandQueueHandle,
+                                                                L2TableAdr + i * GMM_AUX_L2e_SIZE,
+                                                                InvalidEntry.Value);
+                        }
+                    }
+                }
+
+                if(AllocateL1)
+                {
+                    uint64_t InvalidEntry = (!isTRVA) ? GMM_INVALID_AUX_ENTRY : (NullCCSTile | __BIT(0));
+                    uint32_t i            = 0;
+
+                    if(DoNotWait)
+                    {
+                        GmmLib::LastLevelTable *pL1Tbl = NULL;
+                        pL1Tbl                         = pTTL2[L3eIdx].GetL1Table(L2eIdx, NULL);
+                        L2TableCPUAdr = pTTL2[L3eIdx].GetCPUAddress();
+                        L1TableCPUAdr = pL1Tbl->GetCPUAddress();
+                        //Sync update on CPU
+                        ((GMM_AUXTTL2e *)L2TableCPUAdr)[L2eIdx].Value     = 0;
+                        ((GMM_AUXTTL2e *)L2TableCPUAdr)[L2eIdx].L1GfxAddr = L1TableAdr >> 13;
+                        ((GMM_AUXTTL2e *)L2TableCPUAdr)[L2eIdx].Valid     = 1;
+                        for(i = 0; i < (uint32_t)GMM_AUX_L1_SIZE(pGmmGlobalContext); i++)
+                        {
+                            //initialize L1e ie mark all entries with Null tile value
+                            ((GMM_AUXTTL1e *)L1TableCPUAdr)[i].Value = InvalidEntry;
+                        }
+                    }
+                    else
+                    {
+                        GMM_AUXTTL2e L2e = {0};
+                        L2e.Valid        = 1;
+                        L2e.L1GfxAddr    = L1TableAdr >> 13;
+                        pTTL2[L3eIdx].UpdatePoolFence(UmdContext, false);
+                        PageTableMgr->TTCb.pfWriteL2L3Entry(UmdContext->pCommandQueueHandle,
+                                                            L2TableAdr + L2eIdx * GMM_AUX_L2e_SIZE,
+                                                            L2e.Value);
+
+                        //initialize all L1e with invalid entries
+                        for(i = 0; i < (uint32_t)GMM_AUX_L1_SIZE(pGmmGlobalContext); i++)
+                        {
+                            PageTableMgr->TTCb.pfWriteL2L3Entry(UmdContext->pCommandQueueHandle,
+                                                                L1TableAdr + i * sizeof(uint64_t),
+                                                                InvalidEntry);
+                        }
+                    }
+                }
+            }
+
+            GMM_DPF(GFXDBG_CRITICAL, "Mapping surface: GPUVA=0x%016llx Size=0x%08x Aux_GPUVA=0x%016llx", StartAdr, BaseSize, CCS$Adr);
+
+            for(TileAdr = StartAdr; TileAdr < EndAdr; TileAdr += (!WA16K ? GMM_KBYTE(64) : GMM_KBYTE(16)),
+            CCS$Adr += (pGmmGlobalContext->GetSkuTable().FtrLinearCCS ?
+                        (!WA16K ? GMM_BYTES(256) : GMM_BYTES(64)) :
+                        0))
+            {
+                GMM_GFX_SIZE_T L1eIdx = GMM_L1_ENTRY_IDX(AUXTT, TileAdr, pGmmGlobalContext);
+                GMM_AUXTTL1e   L1e    = {0};
+                L1e.Value             = PartialData;
+                L1e.Valid             = 1;
+
+                CCS$Adr = (pGmmGlobalContext->GetSkuTable().FtrLinearCCS ? CCS$Adr :
+                                                                                         __GetCCSCacheline(BaseResInfo, BaseAdr, AuxResInfo, AuxVA, TileAdr - BaseAdr));
+
+                if(!WA16K)
+                {
+                    __GMM_ASSERT((CCS$Adr & 0xFF) == 0x0);
+                    __GMM_ASSERT(GFX_IS_ALIGNED(CCS$Adr, GMM_BYTES(256)));
+                    __GMM_ASSERT(GFX_IS_ALIGNED(TileAdr, GMM_KBYTE(64)));
+                    L1e.GfxAddress = CCS$Adr >> 8; /*********** 256B-aligned CCS adr *****/
+                }
+                else
+                {
+                    L1e.Reserved2  = CCS$Adr >> 6; /*********** 2 lsbs of 64B-aligned CCS adr *****/
+                    L1e.GfxAddress = CCS$Adr >> 8; /*********** 256B-aligned CCS adr *****/
+                }
+
+                //GMM_DPF(GFXDBG_CRITICAL, "Map | L1=0x%016llx[0x%016llx] L1e=[0x%016llx] | [ GPUVA=0x%016llx[0x%08x] Aux_GPUVA=0x%016llx [%s]", L1TableAdr + L1eIdx << 3, L1eIdx << 3, L1e.Value, TileAdr, TileAdr - StartAdr, CCS$Adr, L1e.Valid ? "V" : " ");
+
+                GmmLib::LastLevelTable *pL1Tbl = NULL;
+
+                pL1Tbl        = pTTL2[L3eIdx].GetL1Table(L2eIdx, NULL);
+                L1TableCPUAdr = pL1Tbl->GetCPUAddress();
+                if(DoNotWait)
+                {
+                    //Sync update on CPU
+                    ((GMM_AUXTTL1e *)L1TableCPUAdr)[L1eIdx].Value = L1e.Value;
+
+                    //GMM_DPF(GFXDBG_CRITICAL, "Map | Table Entry: [0x%06x] L2Addr[0x%016llX] Value[0x%016llX] :: [0x%06x] L1Addr[0x%016llX] Value[0x%016llX] -> GPUVA: 0x%016llX[0x%06X] Aux_GPUVA: 0x%016llX [%s]\n", L2eIdx, &((GMM_AUXTTL2e *)L2TableCPUAdr)[L2eIdx], ((GMM_AUXTTL2e *)L2TableCPUAdr)[L2eIdx].L1GfxAddr << 13, L1eIdx, &((GMM_AUXTTL1e *)L1TableCPUAdr)[L1eIdx] /*L1TableAdr + L1eIdx * GMM_AUX_L1e_SIZE*/, L1e.Value, TileAdr, TileAdr - BaseAdr, ((GMM_AUXTTL1e *)L1TableCPUAdr)[L1eIdx].GfxAddress << 6, ((GMM_AUXTTL1e *)L1CPUAdr)[L1eIdx].Valid ? "V" : " ");
+                }
+                else
+                {
+                    pL1Tbl->UpdatePoolFence(UmdContext, false);
+                    PageTableMgr->TTCb.pfWriteL2L3Entry(UmdContext->pCommandQueueHandle,
+                                                        L1TableAdr + L1eIdx * GMM_AUX_L1e_SIZE,
+                                                        L1e.Value);
+                }
+
+                // Since we are mapping a non-null entry, no need to check whether
+                // L1 table is unused.
+                pL1Tbl->TrackTableUsage(AUXTT, true, TileAdr, false);
+            }
+        }
+        if(!DoNotWait)
+        {
+            PageTableMgr->TTCb.pfEpilogTranslationTable(
+            UmdContext->pCommandQueueHandle,
+            1);
+        }
+    }
+
+    LeaveCriticalSection(&TTLock);
+
+    return Status;
+}
+
+GMM_AUXTTL1e GmmLib::AuxTable::CreateAuxL1Data(GMM_RESOURCE_INFO *BaseResInfo)
+{
+    GMM_FORMAT_ENTRY FormatInfo = pGmmGlobalContext->GetPlatformInfo().FormatTable[BaseResInfo->GetResourceFormat()];
+    GMM_AUXTTL1e     L1ePartial = {0};
+#define GMM_REGISTRY_UMD_PATH "SOFTWARE\\Intel\\IGFX\\GMM\\"
+#define GMM_E2EC_OVERRIDEDEPTH16BPPTO12 "ForceYUV16To12BPP"
+
+    L1ePartial.Mode = BaseResInfo->GetResFlags().Info.RenderCompressed ? 0x1 : 0x0; //MC on VCS supports all compression modes,
+                                                                                    //MC on Render pipe only 128B compr (until B-step)
+    //Recognize which .MC surfaces needs Render pipe access
+    if(pGmmGlobalContext->GetWaTable().WaLimit128BMediaCompr)
+    {
+        L1ePartial.Mode = 0x1; //Limit media compression to 128B (same as RC) on gen12LP A0
+    }
+
+    //L1ePartial.Lossy = 0; // when to set it
+    L1ePartial.TileMode = BaseResInfo->GetResFlags().Info.TiledYs ? 0 : 1;
+
+    L1ePartial.Format     = FormatInfo.CompressionFormat.AuxL1eFormat;
+    L1ePartial.LumaChroma = GmmIsPlanar(BaseResInfo->GetResourceFormat());
+
+    if(pGmmGlobalContext->GetWaTable().WaUntypedBufferCompression && BaseResInfo->GetResourceType() == RESOURCE_BUFFER)
+    {
+        //Gen12LP WA to support untyped raw buffer compression on HDC ie MLC(machine-learning compression)
+        L1ePartial.TileMode = 0;
+        L1ePartial.Depth    = 0x6;
+        L1ePartial.Format   = GMM_E2ECOMP_FORMAT_RGBAFLOAT16;
+    }
+
+    __GMM_ASSERT(L1ePartial.Format > GMM_E2ECOMP_MIN_FORMAT && //Are we going to reuse 0x00 for uncompressed indication? CCS contains that info, but only known by HW
+                 L1ePartial.Format <= GMM_E2ECOMP_MAX_FORMAT); //Could SW use it as surface-wide uncompressed state indicator? If so, remove teh assert (Need to make sure, all format encodings are correct)
+
+    if(BaseResInfo->GetResFlags().Info.RenderCompressed)
+    {
+        if(BaseResInfo->GetResourceType() != RESOURCE_BUFFER)
+        {
+            switch(FormatInfo.Element.BitsPer)
+            {
+                case 8:
+                    L1ePartial.Depth = 0x4;
+                    break;
+                case 16:
+                    L1ePartial.Depth = 0x0;
+                    break;
+                case 32:
+                    L1ePartial.Depth = 0x5;
+                    break;
+                case 64:
+                    L1ePartial.Depth = 0x6;
+                    break;
+                case 128:
+                    L1ePartial.Depth = 0x7;
+                    break;
+                default:
+                    L1ePartial.Depth = 0x3;
+            }
+        }
+    }
+    else
+    {
+        switch(BaseResInfo->GetResourceFormat())
+        {
+            case GMM_FORMAT_P012:
+            case GMM_FORMAT_Y412:
+            case GMM_FORMAT_Y212: //which format encoding for Y212, Y412, P012?
+                L1ePartial.Depth = 0x2;
+                break;
+            case GMM_FORMAT_P010:
+            //case GMM_FORMAT_Y410:
+            case GMM_FORMAT_Y210: //which format encoding for Y210?
+                L1ePartial.Depth = 0x1;
+                break;
+            case GMM_FORMAT_P016: //per HAS, separate encoding than P010, but a comment says to use P010 in AuxTable?
+            case GMM_FORMAT_Y416:
+            case GMM_FORMAT_Y216:
+                L1ePartial.Depth = 0x0;
+                break;
+            default:
+                L1ePartial.Depth = 0x3; //For MC, bpp got from format encoding
+        }
+
+        if(L1ePartial.Format == GMM_E2ECOMP_FORMAT_R10G10B10A2_UNORM)
+        {
+            L1ePartial.Format = GMM_E2ECOMP_FORMAT_RGB10b;
+        }
+    }
+
+    return L1ePartial;
+}
+
+GMM_GFX_ADDRESS GMM_INLINE GmmLib::AuxTable::__GetCCSCacheline(GMM_RESOURCE_INFO *BaseResInfo, GMM_GFX_ADDRESS BaseAdr,
+                                                               GMM_RESOURCE_INFO *AuxResInfo, GMM_GFX_ADDRESS AuxVA, GMM_GFX_SIZE_T AdrOffset)
+{
+    GMM_GFX_ADDRESS CCSChunkAdr = 0xFFFFFFF0;
+    uint32_t        x = 0, y = 0;
+    uint32_t        i = 0, j = 0;
+    uint32_t        CCSXTile = 0, CCSYTile = 0;
+    GMM_UNREFERENCED_PARAMETER(BaseAdr);
+
+    bool     BaseIsYF         = BaseResInfo->GetResFlags().Info.TiledYf ? true : false;
+    uint32_t BasePitchInTiles = BaseResInfo->GetRenderPitchTiles();
+
+    //Find YF/YS TileId <x,y> for given main surface 16K-chunk
+    //and CCS$Id <i,j> corresponding to main's <x,y>
+    AdrOffset >>= 14; //AdrOffset must be 16K-aligned chunk, since mapping unit is 4 YF pages
+    if(BaseIsYF)
+    {
+        uint32_t PitchIn4YF = BasePitchInTiles / 4; //Base Pitch is physically padded to 4x1 YF width
+        i                   = static_cast<uint32_t>(AdrOffset % PitchIn4YF);
+        j                   = static_cast<uint32_t>(AdrOffset / PitchIn4YF);
+    }
+    else if(BasePitchInTiles != 0) //TileYs
+    {
+        x = static_cast<uint32_t>(AdrOffset >> 2); //YS-tile count
+        y = x / BasePitchInTiles;                  //YS- tile id <x,y>
+        x = x % BasePitchInTiles;
+        i = 2 * x;
+        j = 2 * y;
+        switch(AdrOffset % 4) //YS : XYXY [XYXY YF] ie 2x2 16K-units in Y-major
+        {
+            case 0:
+                break;
+            case 1:
+                j++;
+                break;
+            case 2:
+                i++;
+                break;
+            case 3:
+                i++;
+                j++;
+                break;
+        }
+    }
+
+    //Compute CCS$ address for <i,j>
+    CCSXTile = (i >= 8) ? i / 8 : 0; //8x8 CLs make one CCS Tile; get TileOffset
+    CCSYTile = (j >= 8) ? j / 8 : 0;
+    i %= 8;
+    j %= 8;
+
+    uint32_t AuxPitchInTiles = AuxResInfo ? AuxResInfo->GetRenderPitchTiles() : BaseResInfo->GetRenderAuxPitchTiles();
+    CCSChunkAdr              = AuxVA + ((CCSXTile + CCSYTile * AuxPitchInTiles) * GMM_KBYTE(4)) + (8 * GMM_BYTES(64) * i) + (GMM_BYTES(64) * j);
+
+    return CCSChunkAdr;
+}
+
+#endif /*!__GMM_KMD__*/
diff --git a/Source/GmmLib/TranslationTable/GmmPageTableMgr.cpp b/Source/GmmLib/TranslationTable/GmmPageTableMgr.cpp
new file mode 100644
index 0000000..55e6a33
--- /dev/null
+++ b/Source/GmmLib/TranslationTable/GmmPageTableMgr.cpp
@@ -0,0 +1,730 @@
+/*==============================================================================
+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: UMD-TT manager (manages both TR-TT and AUX-TT in user mode space)
+
+============================================================================*/
+
+#include "Internal/Common/GmmLibInc.h"
+#include "External/Common/GmmPageTableMgr.h"
+#include "../TranslationTable/GmmUmdTranslationTable.h"
+#include "External/Common/GmmClientContext.h"
+
+#if defined(__linux__)
+#include "Internal/Linux/GmmResourceInfoLinInt.h"
+#endif
+
+#define ENTER_CRITICAL_SECTION           \
+    if(AuxTTObj)                         \
+    {                                    \
+        EnterCriticalSection(&PoolLock); \
+    }
+
+#define EXIT_CRITICAL_SECTION            \
+    if(AuxTTObj)                         \
+    {                                    \
+        LeaveCriticalSection(&PoolLock); \
+    }
+
+#if defined(__linux__)
+GMM_STATUS GmmLib::__GmmDeviceAlloc(GmmClientContext *        pClientContext,
+                                    GMM_DEVICE_CALLBACKS_INT *pDeviceCbInt,
+                                    GMM_DEVICE_ALLOC *        pAlloc)
+{
+    GMM_CLIENT       ClientType;
+    GMM_DDI_ALLOCATE Alloc = {0};
+    int              err;
+
+    GET_GMM_CLIENT_TYPE(pClientContext, ClientType);
+
+    __GMM_ASSERTPTR(GmmCheckForNullDevCbPfn(ClientType, pDeviceCbInt, GMM_DEV_CB_ALLOC), GMM_INVALIDPARAM);
+
+    if(GmmCheckForNullDevCbPfn(ClientType, pDeviceCbInt, GMM_DEV_CB_ALLOC))
+    {
+        Alloc.size      = pAlloc->Size;
+        Alloc.alignment = pAlloc->Alignment;
+
+        err = GmmDeviceCallback(ClientType, pDeviceCbInt, &Alloc);
+        if(err)
+        {
+            return GMM_OUT_OF_MEMORY;
+        }
+
+        pAlloc->GfxVA  = Alloc.gfxAddr;
+        pAlloc->CPUVA  = Alloc.gfxAddr; 
+        pAlloc->Handle = (HANDLE)Alloc.bo;
+    }
+
+    return GMM_SUCCESS;
+}
+
+GMM_STATUS GmmLib::__GmmDeviceDealloc(GMM_CLIENT                ClientType,
+                                      GMM_DEVICE_CALLBACKS_INT *DeviceCb,
+                                      GMM_DEVICE_DEALLOC *      pDealloc)
+{
+    GMM_DDI_DEALLOCATE DeAlloc = {0};
+    int                err     = 0;
+
+    __GMM_ASSERTPTR(GmmCheckForNullDevCbPfn(ClientType, DeviceCb, GMM_DEV_CB_DEALLOC), GMM_INVALIDPARAM);
+
+    if(GmmCheckForNullDevCbPfn(ClientType, DeviceCb, GMM_DEV_CB_DEALLOC))
+    {
+        DeAlloc.bo = pDealloc->Handle;
+
+        err = GmmDeviceCallback(ClientType, DeviceCb, &DeAlloc);
+    }
+
+    return (err == 0) ? GMM_SUCCESS : GMM_ERROR;
+}
+#endif 
+
+//=============================================================================
+//
+// Function: __AllocateNodePool
+//
+// Desc: Allocates (always resident SVM) memory for new Pool node, and updates PageTableMgr object
+//
+// Parameters:
+//      AddrAlignment: Pool allocation address alignment
+//
+// Returns:
+//      S_OK on success,
+//-----------------------------------------------------------------------------
+GmmLib::GMM_PAGETABLEPool *GmmLib::GmmPageTableMgr::__AllocateNodePool(uint32_t AddrAlignment, GmmLib::POOL_TYPE Type)
+{
+    GMM_STATUS         Status      = GMM_SUCCESS;
+    GMM_RESOURCE_INFO *pGmmResInfo = NULL;
+    GMM_PAGETABLEPool *pTTPool     = NULL;
+    HANDLE             PoolHnd     = 0;
+    GMM_CLIENT         ClientType;
+    GMM_DEVICE_ALLOC   Alloc = {0};
+
+    ENTER_CRITICAL_SECTION
+
+    //Allocate pool, sized PAGETABLE_POOL_MAX_NODES pages, assignable to TR/Aux L1/L2 tables
+    //SVM allocation, always resident
+    Alloc.Size      = PAGETABLE_POOL_SIZE;
+    Alloc.Alignment = AddrAlignment;
+    Alloc.hCsr      = hCsr;
+
+    Status = __GmmDeviceAlloc(pClientContext, &DeviceCbInt, &Alloc);
+
+    if(Status != GMM_SUCCESS)
+    {
+        __GMM_ASSERT(0);
+        EXIT_CRITICAL_SECTION
+        return NULL;
+    }
+
+    PoolHnd     = Alloc.Handle;
+    pGmmResInfo = (GMM_RESOURCE_INFO *)Alloc.Priv;
+
+    pTTPool = new GMM_PAGETABLEPool(PoolHnd, pGmmResInfo, Alloc.GfxVA, Alloc.CPUVA, Type);
+
+    __GMM_ASSERTPTR(pTTPool, NULL);
+
+    if(pTTPool)
+    {
+        if(pPool)
+        {
+            NumNodePoolElements++;
+            if(Type == POOL_TYPE_TRTTL2) // TRTT-L2 not 1st node in Pool LinkedList, place it at beginning
+            {
+                pPool = pPool->InsertInListAtBegin(pTTPool);
+            }
+            else
+            {
+                pTTPool = pPool->InsertInList(pTTPool);
+            }
+        }
+        else
+        {
+            NumNodePoolElements = 1;
+            pPool               = pTTPool;
+        }
+    }
+    else
+    {
+        Status = GMM_OUT_OF_MEMORY;
+    }
+
+    EXIT_CRITICAL_SECTION
+    return (Status == GMM_SUCCESS) ? pTTPool : NULL;
+}
+
+//=============================================================================
+//
+// Function: __ReleaseUnusedPool
+//
+// Desc: Frees up unused PageTablePools once residency limit is hit
+//
+// Parameters:
+//      UmdContext: pointer to caller thread's context (containing BBHandle/Fence info)
+//
+//-----------------------------------------------------------------------------
+void GmmLib::GmmPageTableMgr::__ReleaseUnusedPool(GMM_UMD_SYNCCONTEXT *UmdContext)
+{
+    GMM_STATUS                 Status         = GMM_SUCCESS;
+    GMM_GFX_SIZE_T             PoolSizeToFree = {0};
+    GMM_GFX_SIZE_T             FreedSize      = {0};
+    GmmLib::GMM_PAGETABLEPool *Pool = NULL, *PrevPool = NULL;
+    uint32_t                   i = 0;
+    GMM_CLIENT                 ClientType;
+    GMM_DEVICE_DEALLOC         Dealloc;
+
+    GET_GMM_CLIENT_TYPE(pClientContext, ClientType);
+
+    ENTER_CRITICAL_SECTION
+    if(pPool->__IsUnusedTRTTPoolOverLimit(&PoolSizeToFree))
+    {
+        for(i = 0; i < NumNodePoolElements && FreedSize < PoolSizeToFree; i++)
+        {
+            Pool = (PrevPool) ? PrevPool->GetNextPool() : pPool;
+
+            if(Pool->IsPoolInUse(UmdContext ? SyncInfo(UmdContext->BBFenceObj, UmdContext->BBLastFence) : SyncInfo()))
+            {
+                PrevPool = Pool;
+                continue;
+            }
+
+            if(GmmCheckForNullDevCbPfn(ClientType, &DeviceCbInt, GMM_DEV_CB_WAIT_FROM_CPU))
+            {
+                GMM_DDI_WAITFORSYNCHRONIZATIONOBJECTFROMCPU Wait = {0};
+                Wait.bo                                          = Pool->GetPoolHandle();
+                GmmDeviceCallback(ClientType, &DeviceCbInt, &Wait);
+            }
+
+            Dealloc.Handle = Pool->GetPoolHandle();
+            Dealloc.GfxVA  = Pool->GetGfxAddress();
+            Dealloc.Priv   = Pool->GetGmmResInfo();
+            Dealloc.hCsr   = hCsr;
+
+            Status = __GmmDeviceDealloc(ClientType, &DeviceCbInt, &Dealloc);
+
+            __GMM_ASSERT(GMM_SUCCESS == Status);
+
+            if(PrevPool)
+            {
+                PrevPool->GetNextPool() = Pool->GetNextPool();
+            }
+            else
+            {
+                pPool = Pool->GetNextPool();
+            }
+            delete Pool;
+            FreedSize += PAGETABLE_POOL_SIZE;
+        }
+    }
+    EXIT_CRITICAL_SECTION
+}
+
+//=============================================================================
+//
+// Function: __GetFreePoolNode
+//
+// Desc: Finds free node within existing PageTablePool(s), if no such node found,
+//       allocates new PageTablePool. Caller should update Pool Node usage
+//
+// Parameters:
+//      FreePoolNodeIdx: pointer to return Pool's free Node index
+//      PoolType: AuxTT_L1/L2 pool
+//
+// Returns:
+//     PageTablePool element and FreePoolNodeIdx that should be used for L2/L1 assignment
+//     NULL, if no free node exists and new pool allocation failed
+//-----------------------------------------------------------------------------
+GmmLib::GMM_PAGETABLEPool *GmmLib::GmmPageTableMgr::__GetFreePoolNode(uint32_t *FreePoolNodeIdx, POOL_TYPE PoolType)
+{
+    uint32_t PoolNode = -1, i = 0, j = 0, DWdivisor = 1, IdxMultiplier = 1;
+    bool     PoolNodeFound = false, TRTTPool = false;
+
+    ENTER_CRITICAL_SECTION
+    GmmLib::GMM_PAGETABLEPool *Pool = pPool;
+
+    Pool = (PoolType == POOL_TYPE_TRTTL2) ? Pool : //1st pool reserved for TRTT-L2, since TRTT-L2 pruning not supported yet,
+           (Pool ? Pool->GetNextPool() : NULL);    //other pools can be TR-L1/Aux-L1/Aux-L2 (and support dynamic pruning)
+    TRTTPool      = (PoolType == POOL_TYPE_TRTTL2 || PoolType == POOL_TYPE_TRTTL1) ? true : false;
+    DWdivisor     = TRTTPool ? 8 * sizeof(uint32_t) : (PoolType == POOL_TYPE_AUXTTL2) ? 8 * sizeof(uint32_t) * AUX_L2TABLE_SIZE_IN_POOLNODES : 8 * sizeof(uint32_t) * AUX_L1TABLE_SIZE_IN_POOLNODES;
+    IdxMultiplier = TRTTPool ? 1 : (PoolType == POOL_TYPE_AUXTTL2) ? AUX_L2TABLE_SIZE_IN_POOLNODES : AUX_L1TABLE_SIZE_IN_POOLNODES;
+
+    //Scan existing PageTablePools for free pool node
+    for(i = (PoolType == POOL_TYPE_TRTTL2) ? 0 : 1; Pool && i < NumNodePoolElements; i++)
+    {
+        if(Pool->GetNumFreeNode() > 0 && Pool->GetPoolType() == PoolType)
+        {
+            PoolNodeFound    = true;
+            *FreePoolNodeIdx = 0;
+            for(; j < PAGETABLE_POOL_MAX_NODES / DWdivisor; j++)
+            {
+                if(_BitScanForward((uint32_t *)&PoolNode, (uint32_t) ~(Pool->GetNodeUsageAtIndex(j)))) // Get LSB that has value 0
+                {
+                    *FreePoolNodeIdx += PoolNode * IdxMultiplier;
+                    PoolNodeFound = true;
+                    break;
+                }
+                PoolNodeFound = false;
+                *FreePoolNodeIdx += DWdivisor; //DWORD size in bits
+            }
+        }
+        if(PoolNodeFound)
+        {
+            __GMM_ASSERT(Pool->GetPoolType() == PoolType);
+            EXIT_CRITICAL_SECTION
+            return Pool;
+        }
+        Pool = Pool->GetNextPool();
+    }
+
+    //No free pool node, allocate new
+    if(!PoolNodeFound)
+    {
+        GMM_PAGETABLEPool *Pool = NULL;
+        if(Pool = __AllocateNodePool(IdxMultiplier * PAGE_SIZE, PoolType))
+        {
+            __GMM_ASSERT(Pool->GetPoolType() == PoolType);
+
+            *FreePoolNodeIdx = 0;
+            EXIT_CRITICAL_SECTION
+            return Pool;
+        }
+    }
+
+    EXIT_CRITICAL_SECTION
+    return NULL;
+}
+
+
+
+/**********************************************************************************
+** Class GmmPageTableMgr functions **
+***********************************************************************************/
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// Instantiates GmmPageTableMgr, allocating memory for root-tables, copies provided
+/// device-callback function pointers
+///
+/// @param[in]  DeviceCb: pointer sharing device-callback function pointers
+/// @param[in]  TTFlags: Flags specifying which PageTables are required by client
+/// @return     GmmPageTableMgr*
+/////////////////////////////////////////////////////////////////////////////////////
+GmmLib::GmmPageTableMgr::GmmPageTableMgr(GMM_DEVICE_CALLBACKS_INT *DeviceCB, uint32_t TTFlags, GmmClientContext *pClientContextIn)
+    : GmmPageTableMgr()
+{
+    GMM_PAGETABLE_MGR *ptr    = NULL;
+    GMM_STATUS         status = GMM_SUCCESS;
+    GMM_CLIENT         ClientType;
+
+    if(pClientContextIn)
+    {
+        ClientType = pClientContextIn->GetClientType();
+    }
+    else
+    {
+        goto ERROR_CASE;
+    }
+
+    // this is needed if there is an error case and destructor gets called on ptr
+    this->pClientContext = pClientContextIn;
+
+    // Currently coping the code below to GMMOldAPi.cpp for backward compatible.
+    // Any changes here should be copied there.
+    //Initialize PageTableMgr further, only if PageTable creation succeeded
+    try
+    {
+        ptr                 = new GmmPageTableMgr();
+        ptr->pClientContext = pClientContextIn;
+        memcpy(&ptr->DeviceCbInt, DeviceCB, sizeof(GMM_DEVICE_CALLBACKS_INT));
+
+        if(pGmmGlobalContext->GetSkuTable().FtrE2ECompression)
+        {
+            __GMM_ASSERT(TTFlags & AUXTT); //Aux-TT is mandatory
+            ptr->AuxTTObj = new AuxTable();
+            if(!ptr->AuxTTObj)
+            {
+                goto ERROR_CASE;
+            }
+            ptr->AuxTTObj->PageTableMgr   = ptr;
+            ptr->AuxTTObj->pClientContext = pClientContextIn;
+            status                        = ptr->AuxTTObj->AllocateL3Table(8 * PAGE_SIZE, 8 * PAGE_SIZE);
+
+            if(status != GMM_SUCCESS)
+            {
+                InitializeCriticalSection(&(ptr->PoolLock));
+                goto ERROR_CASE;
+            }
+        }
+    }
+
+    catch(...)
+    {
+        __GMM_ASSERT(false);
+        if(ptr && (AuxTTObj))
+        {
+            InitializeCriticalSection(&(ptr->PoolLock));
+        }
+        goto ERROR_CASE;
+    }
+
+    if(status == GMM_SUCCESS && !(AuxTTObj))
+    {
+        if(ptr->AuxTTObj)
+        {
+            ptr->AuxTTObj->PageTableMgr = this;
+        }
+        *this = *ptr;
+        //Don't initialize PoolLock until any of AuxTable object created
+        if(ptr->AuxTTObj )
+        {
+            InitializeCriticalSection(&PoolLock);
+
+        }
+        //Delete temporary ptr, but don't release allocated PageTable Obj.
+        ptr->AuxTTObj = NULL;
+    }
+
+ERROR_CASE:
+    delete ptr;
+    ptr = NULL;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// Returns Root-table address for Aux-table
+///
+/// @return     GMM_GFX_ADDRESS if Aux-Table was created; NULL otherwise
+/////////////////////////////////////////////////////////////////////////////////////
+GMM_GFX_ADDRESS GmmLib::GmmPageTableMgr::GetAuxL3TableAddr()
+{
+    return AuxTTObj ? AuxTTObj->GetL3Address() : NULL;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// Queues commands to initialize Aux-Table registers in the HW context image
+///
+/// @param[in]  initialBBHandle: pointer to BatchBuffer for queuing commands
+/// @param[in]  engType: specifes engine on which the context would run
+/// @return     GMM_SUCCESS if queuing succeeded; GMM_ERROR otherwise
+/////////////////////////////////////////////////////////////////////////////////////
+GMM_STATUS GmmLib::GmmPageTableMgr::InitContextAuxTableRegister(HANDLE CmdQHandle, GMM_ENGINE_TYPE engType)
+{
+    GMM_GFX_ADDRESS MaskedL3GfxAddress = 0ULL;
+    GMM_UNREFERENCED_PARAMETER(engType);
+
+    //Check FtrE2ECompression = 1
+    if(pGmmGlobalContext->GetSkuTable().FtrE2ECompression && AuxTTObj != NULL)
+    {
+        EnterCriticalSection(&AuxTTObj->TTLock);
+        if(CmdQHandle)
+        {
+            //engType = ENGINE_TYPE_RCS;            //use correct offset based on engType (once per-eng offsets known)
+            uint64_t RegOffset = 0, L3AdrReg = 0;
+            GET_L3ADROFFSET(0, L3AdrReg);
+
+            RegOffset = (L3AdrReg + sizeof(uint32_t));
+            RegOffset = L3AdrReg | (RegOffset << 0x20);
+
+            MaskedL3GfxAddress = AuxTTObj->GetL3Address();
+
+            //TTCb.pfPrologTranslationTable(CmdQHandle);   //MI_FLUSH, TLBInv not required since its called during context-init
+
+            TTCb.pfWriteL3Adr(CmdQHandle, MaskedL3GfxAddress, RegOffset);
+
+            GMM_DPF(GFXDBG_CRITICAL, "AuxTT Map Address: GPUVA=0x%016llX\n", MaskedL3GfxAddress);
+
+            //TTCb.pfEpilogTranslationTable(CmdQHandle, 0);
+
+            AuxTTObj->GetRegisterStatus() = 0;
+        }
+        else
+        {
+            __GMM_ASSERT(false);
+            LeaveCriticalSection(&AuxTTObj->TTLock);
+            return GMM_INVALIDPARAM;
+        }
+        LeaveCriticalSection(&AuxTTObj->TTLock);
+    }
+    return GMM_SUCCESS;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// Updates the Aux-PageTables, for given base resource, with appropriate mappings
+///
+/// @param[in]  Details of AuxTable update request
+/// @return     GMM_STATUS
+/////////////////////////////////////////////////////////////////////////////////////
+GMM_STATUS GmmLib::GmmPageTableMgr::UpdateAuxTable(const GMM_DDI_UPDATEAUXTABLE *UpdateReq)
+{
+    if(GetAuxL3TableAddr() == NULL)
+    {
+        GMM_ASSERTDPF(0, "Invalid AuxTable update request, AuxTable is not initialized");
+        return GMM_INVALIDPARAM;
+    }
+
+    if(!((UpdateReq->BaseResInfo->GetResFlags().Info.RenderCompressed ||
+          UpdateReq->BaseResInfo->GetResFlags().Info.MediaCompressed) &&
+         ((!UpdateReq->AuxResInfo && UpdateReq->BaseResInfo->GetResFlags().Gpu.UnifiedAuxSurface) ||
+          (UpdateReq->AuxResInfo && UpdateReq->AuxResInfo->GetResFlags().Gpu.CCS))))
+    /*(UpdateReq->BaseResInfo->GetResFlags().Gpu.TiledResource ||
+        UpdateReq->BaseResInfo->GetResFlags().Gpu.Depth) */
+    //Allow Separate Aux for Depth/TR/MSAA/others?
+    {
+        GMM_ASSERTDPF(0, "Invalid AuxTable update request");
+        return GMM_INVALIDPARAM;
+    }
+
+    if(UpdateReq->Map && !(!UpdateReq->BaseResInfo->GetResFlags().Gpu.TiledResource || (UpdateReq->BaseResInfo->GetResFlags().Gpu.TiledResource && UpdateReq->UmdContext && UpdateReq->UmdContext->pCommandQueueHandle)))
+    {
+        //GMM_DPF_CRITICAL("TiledResources must Gpu-update AuxTable, proceeding with CPU-update...");
+
+        //Allowing CPU-update if requested so..
+        if(!UpdateReq->DoNotWait)
+        {
+            return GMM_INVALIDPARAM;
+        }
+    }
+
+    ENTER_CRITICAL_SECTION
+
+    if(UpdateReq->Map)
+    {
+        //Get AuxL1e data (other than CCS-adr) from main surface
+        uint64_t   PartialL1e = AuxTTObj->CreateAuxL1Data(UpdateReq->BaseResInfo).Value;
+        GMM_STATUS Status     = GMM_SUCCESS;
+
+        if(UpdateReq->BaseResInfo->GetResFlags().Gpu.TiledResource)
+        {
+            //Aux-TT is sparsely updated, for TRs, upon change in mapping state ie
+            // null->non-null must be mapped
+            // non-null->null        invalidated on AuxTT
+            uint8_t CpuUpdate = UpdateReq->DoNotWait || !(UpdateReq->UmdContext && UpdateReq->UmdContext->pCommandQueueHandle);
+
+            GMM_GFX_ADDRESS AuxVA = UpdateReq->AuxSurfVA;
+            if(UpdateReq->BaseResInfo->GetResFlags().Gpu.UnifiedAuxSurface)
+            {
+                GMM_UNIFIED_AUX_TYPE AuxType = GMM_AUX_CCS;
+                AuxType                      = (UpdateReq->BaseResInfo->GetResFlags().Gpu.Depth && UpdateReq->BaseResInfo->GetResFlags().Gpu.CCS) ? GMM_AUX_ZCS : AuxType;
+                AuxVA                        = UpdateReq->BaseGpuVA + GmmResGetAuxSurfaceOffset(UpdateReq->BaseResInfo, AuxType);
+            }
+
+        }
+        else
+        {
+            GMM_GFX_ADDRESS AuxVA      = {0};
+            GMM_GFX_ADDRESS UVAuxVA    = {0};
+            GMM_GFX_SIZE_T  YPlaneSize = 0;
+            uint32_t        MaxPlanes  = 1;
+
+            if(!UpdateReq->AuxResInfo && UpdateReq->BaseResInfo->GetResFlags().Gpu.UnifiedAuxSurface)
+            {
+                GMM_UNIFIED_AUX_TYPE AuxType = GMM_AUX_CCS;
+                AuxType                      = (UpdateReq->BaseResInfo->GetResFlags().Gpu.Depth &&
+                           UpdateReq->BaseResInfo->GetResFlags().Gpu.CCS) ?
+                          GMM_AUX_ZCS :
+                          AuxType;
+
+                AuxVA = UpdateReq->BaseGpuVA + GmmResGetAuxSurfaceOffset(UpdateReq->BaseResInfo, AuxType);
+
+                //For UV Packed, Gen12 e2e compr supported formats have 2 planes per surface
+                //Each has distinct Aux surface, Y-plane/UV-plane must be mapped to respective Y/UV Aux surface
+                if(GmmIsPlanar(UpdateReq->BaseResInfo->GetResourceFormat()))
+                {
+                    GMM_REQ_OFFSET_INFO ReqInfo = {0};
+                    ReqInfo.Plane               = GMM_PLANE_U;
+                    ReqInfo.ReqRender           = 1;
+
+                    MaxPlanes = 2;
+                    UpdateReq->BaseResInfo->GetOffset(ReqInfo);
+                    YPlaneSize = ReqInfo.Render.Offset64;
+
+                    UVAuxVA = UpdateReq->BaseGpuVA + GmmResGetAuxSurfaceOffset(UpdateReq->BaseResInfo, GMM_AUX_UV_CCS);
+                }
+            }
+
+            //Per-plane Aux-TT map called with per-plane base/Aux address/size
+            for(uint32_t i = 0; i < MaxPlanes; i++)
+            {
+                GMM_GFX_SIZE_T SurfSize = (MaxPlanes > 1 && UpdateReq->BaseResInfo->GetArraySize() > 1) ?
+                                          (UpdateReq->BaseResInfo->GetQPitchPlanar(GMM_NO_PLANE) * UpdateReq->BaseResInfo->GetRenderPitch()) :
+                                          UpdateReq->BaseResInfo->GetSizeMainSurface();
+                GMM_GFX_SIZE_T MapSize = (i == 0) ? ((MaxPlanes > 1) ? YPlaneSize : SurfSize) : SurfSize - YPlaneSize;
+
+                GMM_GFX_ADDRESS BaseSurfVA = (UpdateReq->AuxResInfo || i == 0) ? UpdateReq->BaseGpuVA :
+                                                                                 UpdateReq->BaseGpuVA + YPlaneSize;
+                GMM_GFX_ADDRESS AuxSurfVA = (UpdateReq->AuxResInfo) ? UpdateReq->AuxSurfVA : (i > 0 ? UVAuxVA : AuxVA);
+
+                //Luma plane reset LumaChroma bit
+                ((GMM_AUXTTL1e *)&PartialL1e)->LumaChroma = (i == 0) ? 0 : 1;
+                uint32_t ArrayEle                         = GFX_MAX(((MaxPlanes > 1) ?
+                                             UpdateReq->BaseResInfo->GetArraySize() :
+                                             1),
+                                            1);
+
+                for(uint32_t j = 0; j < ArrayEle; j++)
+                {
+                    BaseSurfVA += ((j > 0) ? (UpdateReq->BaseResInfo->GetQPitchPlanar(GMM_PLANE_Y) * UpdateReq->BaseResInfo->GetRenderPitch()) : 0);
+                    AuxSurfVA += (UpdateReq->AuxResInfo ?
+                                  ((j > 0) ? (UpdateReq->AuxResInfo->GetQPitchPlanar(GMM_PLANE_Y) * UpdateReq->BaseResInfo->GetRenderPitch()) : 0) :
+                                  ((j > 0) ? UpdateReq->BaseResInfo->GetAuxQPitch() : 0));
+
+                    //(Flat mapping): Remove main/aux resInfo from params
+                    Status = AuxTTObj->MapValidEntry(UpdateReq->UmdContext, BaseSurfVA, MapSize, UpdateReq->BaseResInfo,
+                                                     AuxSurfVA, UpdateReq->AuxResInfo, PartialL1e, 1);
+                    if(Status != GMM_SUCCESS)
+                    {
+                        GMM_ASSERTDPF(0, "Insufficient memory, free resources and try again");
+                        EXIT_CRITICAL_SECTION
+                        return Status;
+                    }
+                }
+            }
+        }
+    }
+    else
+    {
+        //Invalidate all mappings for given main surface
+        AuxTTObj->InvalidateTable(UpdateReq->UmdContext, UpdateReq->BaseGpuVA, UpdateReq->BaseResInfo->GetSizeMainSurface(), UpdateReq->DoNotWait);
+    }
+
+    EXIT_CRITICAL_SECTION
+    return GMM_SUCCESS;
+}
+
+#if defined(__linux__) && !_WIN32
+/////////////////////////////////////////////////////////////////////////////////////
+/// Gets size of PageTable buffer object (BOs) list
+///
+/// @param[in]  TTFlags: Flags specifying PageTable-type for which BO-count required
+/// @return     non-zero if BO list is created. Zero otherwise.
+/////////////////////////////////////////////////////////////////////////////////////
+int GmmLib::GmmPageTableMgr::GetNumOfPageTableBOs(uint8_t TTFlags)
+{
+    int NumBO = 0;
+
+    __GMM_ASSERTPTR(TTFlags & AUXTT, 0);
+
+    ENTER_CRITICAL_SECTION
+
+    if(AuxTTObj && AuxTTObj->GetL3Handle())
+        NumBO++;
+
+    NumBO += NumNodePoolElements;
+
+    EXIT_CRITICAL_SECTION
+
+    return NumBO;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// Gets size of PageTable buffer object (BOs) list
+///
+/// @param[in]       TTFlags: Flags specifying PageTable-type for which BO-count required
+/// @param[in][out]  BOList: pointer to memory where PageTable BO*(s) must be sent
+/// @return     non-zero if BO list is created. Zero otherwise.
+/////////////////////////////////////////////////////////////////////////////////////
+int GmmLib::GmmPageTableMgr::GetPageTableBOList(uint8_t TTFlags, void *BOList)
+{
+    int                        NumBO   = GetNumOfPageTableBOs(TTFlags);
+    HANDLE *                   Handles = (HANDLE *)BOList;
+    GmmLib::GMM_PAGETABLEPool *Pool;
+
+    __GMM_ASSERTPTR(TTFlags & AUXTT, 0);
+    __GMM_ASSERTPTR(BOList, 0);
+    __GMM_ASSERTPTR(NumBO, 0);
+
+    ENTER_CRITICAL_SECTION
+
+    if(AuxTTObj && AuxTTObj->GetL3Handle())
+        Handles[0] = AuxTTObj->GetL3Handle();
+
+    Pool = pPool;
+
+    for(int i = 0; i < NumNodePoolElements; i++)
+    {
+        if(Pool)
+        {
+            Handles[i + 1] = Pool->GetPoolHandle();
+            Pool           = Pool->GetNextPool();
+        }
+    }
+
+    EXIT_CRITICAL_SECTION
+
+    return NumBO;
+}
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// Releases GmmPageTableMgr, deleting root-tables and existing page-table pools
+/////////////////////////////////////////////////////////////////////////////////////
+GmmLib::GmmPageTableMgr::~GmmPageTableMgr()
+{
+    GMM_CLIENT ClientType;
+
+    GET_GMM_CLIENT_TYPE(pClientContext, ClientType);
+
+
+
+    if(pPool)
+    {
+        ENTER_CRITICAL_SECTION
+        pPool->__DestroyPageTablePool(&DeviceCbInt, hCsr);
+        NumNodePoolElements = 0;
+        EXIT_CRITICAL_SECTION
+    }
+
+    if(AuxTTObj)
+    {
+        DeleteCriticalSection(&PoolLock);
+
+        if(AuxTTObj)
+        {
+            if(AuxTTObj->NullL1Table)
+            {
+                delete AuxTTObj->NullL1Table;
+            }
+            if(AuxTTObj->NullL2Table)
+            {
+                delete AuxTTObj->NullL2Table;
+            }
+            AuxTTObj->DestroyL3Table();
+            delete AuxTTObj;
+            AuxTTObj = NULL;
+        }
+    }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// Instantiates and zeroes out GmmPageTableMgr
+///
+/// @return     GmmPageTableMgr*
+/////////////////////////////////////////////////////////////////////////////////////
+GmmLib::GmmPageTableMgr::GmmPageTableMgr()
+{
+    this->AuxTTObj            = NULL;
+    this->pPool               = NULL;
+    this->NumNodePoolElements = 0;
+    this->pClientContext      = NULL;
+    this->hCsr                = NULL;
+
+    memset(&DeviceCb, 0, sizeof(GMM_DEVICE_CALLBACKS));
+    memset(&DeviceCbInt, 0, sizeof(GMM_DEVICE_CALLBACKS_INT));
+}
+
+
diff --git a/Source/GmmLib/TranslationTable/GmmUmdTranslationTable.cpp b/Source/GmmLib/TranslationTable/GmmUmdTranslationTable.cpp
new file mode 100644
index 0000000..3d94fcc
--- /dev/null
+++ b/Source/GmmLib/TranslationTable/GmmUmdTranslationTable.cpp
@@ -0,0 +1,670 @@
+/*==============================================================================
+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: Contains functions of internal classes 
+             (ie PageTablePool, PageTable, Table), that support
+             user mode page table management
+
+============================================================================*/
+
+#include "Internal/Common/GmmLibInc.h"
+#include "../TranslationTable/GmmUmdTranslationTable.h"
+#include "Internal/Common/Texture/GmmTextureCalc.h"
+
+#if !defined(__GMM_KMD)
+
+#if defined(__linux__)
+#include "Internal/Linux/GmmResourceInfoLinInt.h"
+
+#define _aligned_free(ptr) free(ptr)
+
+#endif
+
+//=============================================================================
+//
+// Function: AllocateL3Table
+//
+// Desc: Allocates (always resident SVM) memory for AUXTT\L3 Table, and updates AUXTT object
+//
+// Parameters:
+//      pAUXTT_Obj: per-device AUX-TT object. Contains AUXTT node info
+//
+// Returns:
+//      GMM_SUCCESS on success,
+//      GMM_INVALIDPARAM on invalid parameter(s)
+//      GMM_OUT_OF_MEMORY on memory allocation failure, failure to make resident
+//-----------------------------------------------------------------------------
+GMM_STATUS GmmLib::PageTable::AllocateL3Table(uint32_t L3TableSize, uint32_t L3AddrAlignment)
+{
+    GMM_STATUS       Status = GMM_SUCCESS;
+    GMM_DEVICE_ALLOC Alloc  = {0};
+
+    __GMM_ASSERTPTR(PageTableMgr, GMM_INVALIDPARAM);
+
+    EnterCriticalSection(&TTLock);
+
+    Alloc.Size      = L3TableSize;
+    Alloc.Alignment = L3AddrAlignment;
+    Alloc.hCsr      = PageTableMgr->hCsr;
+
+    Status = __GmmDeviceAlloc(pClientContext, &PageTableMgr->DeviceCbInt, &Alloc);
+    if(Status != GMM_SUCCESS)
+    {
+        LeaveCriticalSection(&TTLock);
+        return Status;
+    }
+
+    TTL3.GfxAddress         = GMM_GFX_ADDRESS_CANONIZE(Alloc.GfxVA);
+    TTL3.CPUAddress         = Alloc.CPUVA;
+    TTL3.NeedRegisterUpdate = true;
+    TTL3.L3Handle           = (HANDLE)(uintptr_t)Alloc.Handle;
+    TTL3.pGmmResInfo        = (GMM_RESOURCE_INFO *)Alloc.Priv;
+
+    // Invalidate L3e's
+    for(int i = 0; i < (GMM_L3_SIZE(TTType)); i++)
+    {
+        //initialize L3e ie mark all entries with Null tile/invalid value
+        ((GMM_AUXTTL3e *)TTL3.CPUAddress)[i].Value = 0;
+
+    }
+
+    LeaveCriticalSection(&TTLock);
+    return Status;
+}
+
+//=============================================================================
+//
+// Function: __IsUnusedTRTTPoolOverLimit
+//
+// Desc: Checks if unused TRTTPools have reached residency limit and must be freed.
+//
+// Parameters:
+//      pTRTT_Obj: per-device TT object. Contains TT node info
+//      OverLimitSize: Size in bytes that can be freed
+//
+// Returns:
+//      True, if unused TTPool reached max. residency limit
+//      False, otherwise
+//-----------------------------------------------------------------------------
+bool GmmLib::GmmPageTablePool::__IsUnusedTRTTPoolOverLimit(GMM_GFX_SIZE_T *OverLimitSize)
+{
+    GMM_GFX_SIZE_T             UnusedTrTTPoolSize = 0;
+    GmmLib::GMM_PAGETABLEPool *Pool               = NULL;
+
+    Pool = this;
+
+    while(Pool)
+    {
+        if(Pool->NumFreeNodes == PAGETABLE_POOL_MAX_NODES)
+        {
+            UnusedTrTTPoolSize += PAGETABLE_POOL_SIZE;
+        }
+        Pool = Pool->NextPool;
+    }
+
+    *OverLimitSize = (UnusedTrTTPoolSize > PAGETABLE_POOL_MAX_UNUSED_SIZE) ? (UnusedTrTTPoolSize - PAGETABLE_POOL_MAX_UNUSED_SIZE) : 0;
+    return (UnusedTrTTPoolSize > PAGETABLE_POOL_MAX_UNUSED_SIZE) ? true : false;
+}
+
+//=============================================================================
+//
+// Function: AllocateL1L2Table
+//
+// Desc: Assigns pages from AUXTTPool for L1/L2Table for translation of given TRVA
+//
+// Parameters:
+//      pAUXTT_Obj: per-device AUX-TT object. Contains AUXTT node info
+//      TileAddr: Tiled Resource Virtual address
+//
+// Returns:
+//     L2Table/L1Table Address
+//-----------------------------------------------------------------------------
+void GmmLib::PageTable::AllocateL1L2Table(GMM_GFX_ADDRESS TileAddr, GMM_GFX_ADDRESS *L1TableAdr, GMM_GFX_ADDRESS *L2TableAdr)
+{
+    GMM_GFX_ADDRESS         L3TableAdr = GMM_NO_TABLE;
+    uint32_t                L3eIdx     = static_cast<uint32_t>(GMM_L3_ENTRY_IDX(TTType, TileAddr));
+    uint32_t                L2eIdx     = static_cast<uint32_t>(GMM_L2_ENTRY_IDX(TTType, TileAddr));
+    GmmLib::LastLevelTable *pL1Tbl     = NULL;
+
+    *L2TableAdr = GMM_NO_TABLE;
+    *L1TableAdr = GMM_NO_TABLE;
+
+    if(TTL3.L3Handle)
+    {
+        L3TableAdr = TTL3.GfxAddress;
+    }
+    else
+    {
+        //Should never hit -- L3Table is allocated during device creation
+        __GMM_ASSERT(false);
+    }
+
+    if(pTTL2[L3eIdx].GetPool())
+    {
+        GmmLib::GMM_PAGETABLEPool *PoolElem = NULL;
+        PoolElem                            = pTTL2[L3eIdx].GetPool();
+        *L2TableAdr                         = (PoolElem != NULL) ? PoolElem->GetGfxAddress() + (PAGE_SIZE * pTTL2[L3eIdx].GetNodeIdx()) : GMM_NO_TABLE;
+    }
+    else
+    {
+        uint32_t                   PoolNodeIdx = PAGETABLE_POOL_MAX_NODES;
+        GmmLib::GMM_PAGETABLEPool *PoolElem    = NULL;
+        POOL_TYPE                  PoolType    = POOL_TYPE_AUXTTL2;
+        PoolElem                               = PageTableMgr->__GetFreePoolNode(&PoolNodeIdx, PoolType);
+        if(PoolElem)
+        {
+            pTTL2[L3eIdx] = MidLevelTable(PoolElem, PoolNodeIdx, PoolElem->GetNodeBBInfoAtIndex(PoolNodeIdx));
+            *L2TableAdr   = PoolElem->GetGfxAddress() + PAGE_SIZE * PoolNodeIdx; //PoolNodeIdx must be multiple of 8 (Aux L2) and multiple of 2 (Aux L1)
+            ASSIGN_POOLNODE(PoolElem, PoolNodeIdx, NodesPerTable)
+        }
+    }
+
+    pL1Tbl = pTTL2[L3eIdx].GetL1Table(L2eIdx);
+    if(pL1Tbl)
+    {
+        GmmLib::GMM_PAGETABLEPool *PoolElem = NULL;
+        PoolElem                            = pL1Tbl->GetPool();
+        *L1TableAdr                         = (PoolElem != NULL) ? PoolElem->GetGfxAddress() + (PAGE_SIZE * pL1Tbl->GetNodeIdx()) : GMM_NO_TABLE;
+    }
+    else
+    {
+        //Allocate L1 Table
+        uint32_t                   PoolNodeIdx = PAGETABLE_POOL_MAX_NODES;
+        GmmLib::GMM_PAGETABLEPool *PoolElem    = NULL;
+        POOL_TYPE                  PoolType    = POOL_TYPE_AUXTTL1;
+
+        PoolElem = PageTableMgr->__GetFreePoolNode(&PoolNodeIdx, PoolType); //Recognize if Aux-L1 being allocated
+        if(PoolElem)
+        {
+            pL1Tbl = new GmmLib::LastLevelTable(PoolElem, PoolNodeIdx, GMM_L1_SIZE_DWORD(TTType, pGmmGlobalContext), L2eIdx); //use Aux L1_Size_DWORD
+
+            if(pL1Tbl)
+            {
+                *L1TableAdr = PoolElem->GetGfxAddress() + PAGE_SIZE * PoolNodeIdx; //PoolNodeIdx should reflect 1 node per Tr-table and 2 nodes per AUX L1 TABLE
+                if(PoolNodeIdx != PAGETABLE_POOL_MAX_NODES)
+                {
+                    uint32_t PerTableNodes = (TTType == AUXTT) ? AUX_L1TABLE_SIZE_IN_POOLNODES : 1;
+                    ASSIGN_POOLNODE(PoolElem, PoolNodeIdx, PerTableNodes)
+                }
+                pTTL2[L3eIdx].InsertInList(pL1Tbl);
+            }
+        }
+    }
+}
+
+//=============================================================================
+//
+// Function: AllocateDummyTables
+//
+// Desc: Assigns pages from AUXTTPool for Dummy L1/L2Table
+//
+// Parameters:
+//     L2Table - Ptr to initiatize dummy L2Table
+//     L1Table - Ptr to initiatize dummy L1Table
+//
+// Returns:
+//     L2Table/L1Tables
+//-----------------------------------------------------------------------------
+void GmmLib::PageTable::AllocateDummyTables(GmmLib::Table **L2Table, GmmLib::Table **L1Table)
+{
+    GMM_GFX_ADDRESS         L3TableAdr = GMM_NO_TABLE;
+    GmmLib::LastLevelTable *pL1Tbl     = NULL;
+
+    if(TTL3.L3Handle)
+    {
+        L3TableAdr = TTL3.GfxAddress;
+    }
+    else
+    {
+        //Should never hit -- L3Table is allocated during device creation
+        __GMM_ASSERT(false);
+    }
+
+    //Allocate dummy L2Table
+    {
+        uint32_t                   PoolNodeIdx = PAGETABLE_POOL_MAX_NODES;
+        GmmLib::GMM_PAGETABLEPool *PoolElem    = NULL;
+        POOL_TYPE                  PoolType    = POOL_TYPE_AUXTTL2;
+        PoolElem                               = PageTableMgr->__GetFreePoolNode(&PoolNodeIdx, PoolType);
+        if(PoolElem)
+        {
+            *L2Table = new GmmLib::MidLevelTable(PoolElem, PoolNodeIdx, PoolElem->GetNodeBBInfoAtIndex(PoolNodeIdx));
+            ASSIGN_POOLNODE(PoolElem, PoolNodeIdx, NodesPerTable)
+        }
+    }
+
+    //Allocate dummy L1Table
+    {
+        uint32_t                   PoolNodeIdx = PAGETABLE_POOL_MAX_NODES;
+        GmmLib::GMM_PAGETABLEPool *PoolElem    = NULL;
+        POOL_TYPE                  PoolType    = POOL_TYPE_AUXTTL1;
+
+        PoolElem = PageTableMgr->__GetFreePoolNode(&PoolNodeIdx, PoolType); //Recognize if Aux-L1 being allocated
+        if(PoolElem)
+        {
+            *L1Table = new GmmLib::LastLevelTable(PoolElem, PoolNodeIdx, GMM_L1_SIZE_DWORD(TTType, pGmmGlobalContext), 0); //use Aux L1_Size_DWORD
+
+            if(*L1Table)
+            {
+                if(PoolNodeIdx != PAGETABLE_POOL_MAX_NODES)
+                {
+                    uint32_t PerTableNodes = (TTType == AUXTT) ? AUX_L1TABLE_SIZE_IN_POOLNODES : 1;
+                    ASSIGN_POOLNODE(PoolElem, PoolNodeIdx, PerTableNodes)
+                }
+            }
+        }
+    }
+}
+
+//=============================================================================
+//
+// Function: GetL1L2TableAddr
+//
+// Desc: For given tile address, returns L1/L2 Table address if the table exists
+//
+// Parameters:
+//      pAUXTT_Obj: per-device AUX-TT object. Contains AXUTT node info
+//      TileAddr: Tiled Resource Virtual address
+//
+// Returns:
+//     L2Table/L1Table Address
+//-----------------------------------------------------------------------------
+void GmmLib::PageTable::GetL1L2TableAddr(GMM_GFX_ADDRESS TileAddr, GMM_GFX_ADDRESS *L1TableAdr, GMM_GFX_ADDRESS *L2TableAdr)
+{
+    GMM_GFX_SIZE_T  L3eIdx, L2eIdx, L1eIdx;
+    GMM_GFX_ADDRESS L3TableAdr = GMM_NO_TABLE;
+    *L2TableAdr                = GMM_NO_TABLE;
+    *L1TableAdr                = GMM_NO_TABLE;
+
+    L3eIdx = GMM_L3_ENTRY_IDX(TTType, TileAddr);
+    L2eIdx = GMM_L2_ENTRY_IDX(TTType, TileAddr);
+    L1eIdx = GMM_L1_ENTRY_IDX(TTType, TileAddr, pGmmGlobalContext);
+
+    __GMM_ASSERT(TTL3.L3Handle);
+    L3TableAdr = TTL3.GfxAddress;
+    if(pTTL2[L3eIdx].GetPool())
+    {
+        GmmLib::GMM_PAGETABLEPool *Pool   = NULL;
+        GmmLib::LastLevelTable *   pL1Tbl = NULL;
+        Pool                              = pTTL2[L3eIdx].GetPool();
+
+        if(Pool)
+        {
+            __GMM_ASSERT(Pool->GetNumFreeNode() != PAGETABLE_POOL_MAX_NODES);
+            __GMM_ASSERT(pTTL2[L3eIdx].GetNodeIdx() < PAGETABLE_POOL_MAX_NODES);
+            __GMM_ASSERT(Pool->GetNodeUsageAtIndex(pTTL2[L3eIdx].GetNodeIdx() / (32 * NodesPerTable)) != 0);
+
+            *L2TableAdr = Pool->GetGfxAddress() + PAGE_SIZE * (pTTL2[L3eIdx].GetNodeIdx());
+        }
+
+        pL1Tbl = pTTL2[L3eIdx].GetL1Table(L2eIdx);
+        if(pL1Tbl && pL1Tbl->GetPool())
+        {
+            Pool = NULL;
+            Pool = pL1Tbl->GetPool();
+            if(Pool)
+            {
+                uint32_t PerTableNodes = (TTType == AUXTT) ? AUX_L1TABLE_SIZE_IN_POOLNODES : 1;
+                __GMM_ASSERT(Pool->GetNumFreeNode() != PAGETABLE_POOL_MAX_NODES);
+                __GMM_ASSERT(pL1Tbl->GetNodeIdx() < PAGETABLE_POOL_MAX_NODES);
+                __GMM_ASSERT(Pool->GetNodeUsageAtIndex(pL1Tbl->GetNodeIdx() / (32 * PerTableNodes)) != 0);
+
+                *L1TableAdr = Pool->GetGfxAddress() + PAGE_SIZE * (pL1Tbl->GetNodeIdx());
+            }
+        }
+    }
+}
+
+//=============================================================================
+//
+// Function: GetMappingType
+//
+// Desc: For given gfx address and size, returns MappingType (null/non-null or
+//       Valid/Invalid) of GfxVA and first gfx address have reverse mapping
+//
+/// @param[in] GfxVA: Gfx Address whose mapping type is being queried
+/// @param[in] Size:  Size of interested Gfx address range
+/// @param[out] LastAddr : 1st Gfx Address having reverse mapping type
+//
+/// @return    1/0 : for non-null/valid vs null/invalid mapping
+//-----------------------------------------------------------------------------
+uint8_t GmmLib::PageTable::GetMappingType(GMM_GFX_ADDRESS GfxVA, GMM_GFX_SIZE_T Size, GMM_GFX_ADDRESS &LastAddr)
+{
+    GMM_GFX_SIZE_T  L3eIdx, L2eIdx, L1eIdx, L1EntrySize;
+    uint8_t         MapType      = 0; //true for non-null, false for null mapped
+    bool            bFoundLastVA = false, bTerminate = false;
+    GMM_GFX_ADDRESS TileAddr = GfxVA;
+
+    L3eIdx      = GMM_L3_ENTRY_IDX(TTType, GfxVA);
+    L2eIdx      = GMM_L2_ENTRY_IDX(TTType, GfxVA);
+    L1eIdx      = GMM_L1_ENTRY_IDX(TTType, GfxVA, pGmmGlobalContext);
+    L1EntrySize = !WA16K ? GMM_KBYTE(64) : GMM_KBYTE(16);
+
+    EnterCriticalSection(&TTLock);
+    __GMM_ASSERT(TTL3.L3Handle);
+
+#define GET_NEXT_L1TABLE(L1eIdx, L2eIdx, L3eIdx) \
+    {                                            \
+        L1eIdx = 0;                              \
+        L2eIdx++;                                \
+        if(L2eIdx == (GMM_L2_SIZE(TTType)))      \
+        {                                        \
+            L2eIdx = 0;                          \
+            L3eIdx++;                            \
+            if(L3eIdx == (GMM_L3_SIZE(TTType)))  \
+            {                                    \
+                bTerminate = true;               \
+            }                                    \
+        }                                        \
+    }
+
+#define GET_NEXT_L2TABLE(L1eIdx, L2eIdx, L3eIdx) \
+    {                                            \
+        L1eIdx = L2eIdx = 0;                     \
+        L3eIdx++;                                \
+        if(L3eIdx == (GMM_L3_SIZE(TTType)))      \
+        {                                        \
+            bTerminate = true;                   \
+        }                                        \
+    }
+
+    while(!(bFoundLastVA || bTerminate) && (TileAddr < GfxVA + Size))
+    {
+        if(pTTL2[L3eIdx].GetPool())
+        {
+            GmmLib::LastLevelTable *pL1Tbl = NULL;
+            pL1Tbl                         = pTTL2[L3eIdx].GetL1Table(L2eIdx);
+            if(pL1Tbl && pL1Tbl->GetPool())
+            {
+                uint32_t LastBit = 0;
+                uint32_t i       = static_cast<uint32_t>(L1eIdx) / 32;
+
+                while(!bFoundLastVA && i < (uint32_t)(GMM_L1_SIZE_DWORD(TTType, pGmmGlobalContext)))
+                {
+                    uint32_t UsageDW = pL1Tbl->GetUsedEntries()[i++];
+                    uint32_t BitNum  = 31;
+                    if(GfxVA == TileAddr)
+                    {
+                        BitNum  = L1eIdx % 32;
+                        MapType = ((UsageDW & __BIT(BitNum)) ? 0x1 : 0x0); //true for non-null, false for null mapped
+                        UsageDW = (!MapType) ? UsageDW : ~UsageDW;
+                        UsageDW = ((uint64_t)UsageDW >> (BitNum + 1)) << (BitNum + 1); // clear lsb <= BitNum
+                    }
+                    else
+                    {
+                        UsageDW = (!MapType) ? UsageDW : ~UsageDW;
+                    }
+
+                    if(_BitScanForward((uint32_t *)&LastBit, UsageDW)) // Gets lsb > BitNum, having reverse mapType
+                    {
+                        bFoundLastVA      = true;
+                        uint32_t NumTiles = (GfxVA == TileAddr) ? (LastBit - BitNum) : LastBit;
+                        LastAddr          = TileAddr + NumTiles * L1EntrySize;
+                    }
+                    else
+                    {
+                        uint32_t NumTiles = (GfxVA == TileAddr) ? (32 - BitNum) : 32;
+                        TileAddr += NumTiles * L1EntrySize;
+                    }
+                }
+                if(!bFoundLastVA)
+                {
+                    GET_NEXT_L1TABLE(L1eIdx, L2eIdx, L3eIdx);
+                }
+            }
+            else //L2Entry is NULL
+            {
+                if(MapType) //First hit null-map
+                {
+                    LastAddr     = TileAddr;
+                    bFoundLastVA = true;
+                }
+                else
+                {
+                    GMM_GFX_SIZE_T NumTiles = GMM_L1_SIZE(TTType, pGmmGlobalContext);
+                    if(GfxVA == TileAddr)
+                    {
+                        MapType = false;
+                        NumTiles -= L1eIdx;
+                    }
+                    TileAddr += NumTiles * L1EntrySize;
+                    GET_NEXT_L1TABLE(L1eIdx, L2eIdx, L3eIdx)
+                }
+            }
+        }
+        else //L3entry is NULL
+        {
+            if(MapType) //First hit null-map
+            {
+                LastAddr     = TileAddr;
+                bFoundLastVA = true;
+            }
+            else
+            {
+                GMM_GFX_SIZE_T NumTiles = 0;
+                if(GfxVA == TileAddr)
+                {
+                    MapType  = false;
+                    NumTiles = (GMM_L2_SIZE(TTType) - L2eIdx) * (GMM_L1_SIZE(TTType, pGmmGlobalContext) - L1eIdx);
+                }
+                else
+                {
+                    NumTiles = ((GMM_L2_SIZE(TTType)) * (GMM_L1_SIZE(TTType, pGmmGlobalContext)));
+                }
+                TileAddr += NumTiles * L1EntrySize;
+                GET_NEXT_L2TABLE(L1eIdx, L2eIdx, L3eIdx)
+            }
+        }
+    }
+
+    if(!bFoundLastVA)
+    {
+        LastAddr = TileAddr;
+    }
+
+    LeaveCriticalSection(&TTLock);
+    return MapType;
+}
+
+//=============================================================================
+//
+// Function: TrackTableUsage
+//
+// Desc: For given tile address, updates Table Usage.If Table has all Nullmappings
+//       then its pool node can be unassigned
+//
+// Parameters:
+//      Type:  Translation Table type (Aux)
+//      IsL1:  Is called for L1table or L2 Table
+//      TileAddr: Tiled Resource Virtual address
+//      NullMapped: true if given tiled adr was null mapped, otherwise false
+//
+// Returns:
+//     true, if Table for given tile adr is all null mapped
+//     false,if Table does not exist or has non-null mapping
+//-----------------------------------------------------------------------------
+bool GmmLib::Table::TrackTableUsage(TT_TYPE Type, bool IsL1, GMM_GFX_ADDRESS TileAdr, bool NullMapped)
+{
+    uint32_t EntryIdx;
+    uint32_t ElemNum = 0, BitNum = 0;
+
+    EntryIdx = IsL1 ? static_cast<uint32_t>(GMM_L1_ENTRY_IDX(Type, TileAdr, pGmmGlobalContext)) : static_cast<uint32_t>(GMM_L2_ENTRY_IDX(Type, TileAdr));
+
+    ElemNum = EntryIdx / (sizeof(UsedEntries[0]) * 8);
+    BitNum  = EntryIdx % (sizeof(UsedEntries[0]) * 8);
+
+    if(NullMapped)
+    {
+        UsedEntries[ElemNum] &= ~(1 << BitNum);
+    }
+    else
+    {
+        UsedEntries[ElemNum] |= (1 << BitNum);
+    }
+
+    if(NullMapped)
+    {
+        int TableDWSize = IsL1 ? static_cast<int>(GMM_L1_SIZE_DWORD(Type, pGmmGlobalContext)) : static_cast<int>(GMM_L2_SIZE_DWORD(Type));
+        for(int i = 0; i < TableDWSize; i++)
+        {
+            if(UsedEntries[i])
+            {
+                return false;
+            }
+        }
+    }
+    return NullMapped ? true : false;
+}
+
+//=============================================================================
+//
+// Function: __IsTableNullMapped
+//
+// Desc: For given tile address, checks if given Table has all Nullmappings
+//       then its pool node can be unassigned
+//
+// Parameters:
+//      Type:  Translation Table type (TR or Aux)
+//      IsL1:  Is called for L1table or L2 Table
+//      TileAddr: Tiled Resource Virtual address
+//
+// Returns:
+//     true, if Table for given tile adr is all null mapped
+//     false,if Table has non-null mapping
+//-----------------------------------------------------------------------------
+bool GmmLib::Table::IsTableNullMapped(TT_TYPE Type, bool IsL1, GMM_GFX_ADDRESS TileAdr)
+{
+    GMM_UNREFERENCED_PARAMETER(TileAdr);
+    int TableDWSize = IsL1 ? static_cast<int>(GMM_L1_SIZE_DWORD(Type, pGmmGlobalContext)) : static_cast<int>(GMM_L2_SIZE_DWORD(Type));
+    for(int i = 0; i < TableDWSize; i++)
+    {
+        if(UsedEntries[i])
+        {
+            return false;
+        }
+    }
+    return true;
+}
+
+//=============================================================================
+//
+// Function: __UpdatePoolFence
+//
+// Desc: Updates AUXTTPool's or Table's BBFenceObj/value with current BB fence
+//
+// Parameters:
+//      pAUXTT_Obj: per-device AUX-TT object. Contains AUXTT node info
+//      Table:     L1/L2 table pointer
+//      L1Table:   true for L1 Table, else false
+//      ClearNode: if true, Fence info is cleared for table
+//                    false, Fence info is updated for table and pool
+//-----------------------------------------------------------------------------
+void GmmLib::Table::UpdatePoolFence(GMM_UMD_SYNCCONTEXT *UmdContext, bool ClearNode)
+{
+    if(!ClearNode)
+    {
+        //update both node and pool with current fence/handle
+        PoolElem->GetPoolBBInfo().BBQueueHandle =
+        BBInfo.BBQueueHandle = UmdContext->BBFenceObj;
+        PoolElem->GetPoolBBInfo().BBFence =
+        BBInfo.BBFence = UmdContext->BBLastFence + 1; //Save incremented fence value, since DX does it during submission
+    }
+    else
+    {
+        //Clear node fence/handle
+        BBInfo.BBQueueHandle = 0;
+        BBInfo.BBFence       = 0;
+    }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// Releases all PageTable Pool(s) existing in Linked List
+///
+/// @param[in]  DeviceCallbacks   pointer to device callbacks structure
+/// @return     GMM_STATUS
+/////////////////////////////////////////////////////////////////////////////////////
+GMM_STATUS GmmLib::GmmPageTablePool::__DestroyPageTablePool(void *DeviceCallbacks, HANDLE hCsr)
+{
+    GMM_STATUS                Status   = GMM_SUCCESS;
+    GMM_DEVICE_CALLBACKS_INT *DeviceCb = static_cast<GMM_DEVICE_CALLBACKS_INT *>(DeviceCallbacks);
+
+    GMM_PAGETABLEPool *Node = this, *Next = NULL;
+    GMM_CLIENT         ClientType;
+    GMM_DEVICE_DEALLOC Dealloc = {0};
+
+    //Evict/Free gpu Va is implictly done by OS when de-allocating
+    while(Node)
+    {
+        Next = Node->NextPool;
+
+        GET_GMM_CLIENT_TYPE(Node->pClientContext, ClientType);
+
+        Dealloc.Handle = Node->PoolHandle;
+        Dealloc.GfxVA  = Node->PoolGfxAddress;
+        Dealloc.Priv   = Node->pGmmResInfo;
+        Dealloc.hCsr   = hCsr;
+
+        Status = __GmmDeviceDealloc(ClientType, DeviceCb, &Dealloc);
+
+        Node->PoolHandle     = NULL;
+        Node->PoolGfxAddress = 0;
+        delete Node;
+        Node = Next;
+    }
+
+    return Status;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+/// Releases memory allocated to PageTable's Root-table
+///
+/// @return     GMM_STATUS
+/////////////////////////////////////////////////////////////////////////////////////
+GMM_STATUS GmmLib::PageTable::DestroyL3Table()
+{
+    GMM_STATUS         Status = GMM_SUCCESS;
+    uint8_t            hr     = GMM_SUCCESS;
+    GMM_CLIENT         ClientType;
+    GMM_DEVICE_DEALLOC Dealloc = {0};
+
+    GET_GMM_CLIENT_TYPE(pClientContext, ClientType);
+
+    EnterCriticalSection(&TTLock);
+
+    if(TTL3.L3Handle)
+    {
+        Dealloc.Handle = TTL3.L3Handle;
+        Dealloc.GfxVA  = TTL3.GfxAddress;
+        Dealloc.Priv   = TTL3.pGmmResInfo;
+        Dealloc.hCsr   = PageTableMgr->hCsr;
+
+        Status = __GmmDeviceDealloc(ClientType, &PageTableMgr->DeviceCbInt, &Dealloc);
+
+        TTL3.L3Handle   = NULL;
+        TTL3.GfxAddress = 0;
+        TTL3.CPUAddress = 0;
+    }
+
+    LeaveCriticalSection(&TTLock);
+    return Status;
+}
+
+#endif //!__GMM_KMD
diff --git a/Source/GmmLib/TranslationTable/GmmUmdTranslationTable.h b/Source/GmmLib/TranslationTable/GmmUmdTranslationTable.h
new file mode 100644
index 0000000..4844054
--- /dev/null
+++ b/Source/GmmLib/TranslationTable/GmmUmdTranslationTable.h
@@ -0,0 +1,531 @@
+/*==============================================================================
+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;
+
+    i = ffsl(mask);
+    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)/ (PerTableNodes)) = 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) { return NodeBBInfo[j]; }
+        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
+        {
+            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;
+        } 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)
+        {
+            memset(&TTL3, 0, sizeof(TTL3));
+
+            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
+
diff --git a/Source/GmmLib/ULT/CMakeLists.txt b/Source/GmmLib/ULT/CMakeLists.txt
index 6f51725..e5c2f21 100644
--- a/Source/GmmLib/ULT/CMakeLists.txt
+++ b/Source/GmmLib/ULT/CMakeLists.txt
@@ -1,141 +1,152 @@
-# Copyright(c) 2017 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.

-

-set (EXE_NAME GMMULT)

-

-set(GMMULT_HEADERS

-     GmmCachePolicyULT.h

-     GmmCommonULT.h

-     GmmGen10CachePolicyULT.h

-     GmmGen10ResourceULT.h

-     GmmGen11CachePolicyULT.h

-     GmmGen11ResourceULT.h

-     GmmGen12ResourceULT.h

-     GmmGen12CachePolicyULT.h

-     GmmGen9CachePolicyULT.h

-     GmmGen9ResourceULT.h

-     GmmResourceULT.h

-     stdafx.h

-     targetver.h

-     )

-

-set(GMMULT_SOURCES

-    GmmCachePolicyULT.cpp

-    GmmCommonULT.cpp

-    GmmGen10CachePolicyULT.cpp

-    GmmGen10ResourceULT.cpp

-    GmmGen11CachePolicyULT.cpp

-    GmmGen12CachePolicyULT.cpp

-    GmmGen11ResourceULT.cpp

-    GmmGen12ResourceULT.cpp

-    GmmGen9CachePolicyULT.cpp

-    GmmGen9ResourceULT.cpp

-    GmmResourceCpuBltULT.cpp

-    GmmResourceULT.cpp

-    googletest/src/gtest-all.cc

-    GmmULT.cpp

-)

-

-source_group("Source Files\\Cache Policy" FILES

-            GmmCachePolicyULT.cpp

-            GmmGen9CachePolicyULT.cpp

-            GmmGen10CachePolicyULT.cpp

-            GmmGen11CachePolicyULT.cpp

-            GmmGen12CachePolicyULT.cpp

-            )

-

-source_group("Source Files\\Resource" FILES

-            GmmGen10ResourceULT.cpp

-            GmmGen11ResourceULT.cpp

-            GmmGen12ResourceULT.cpp

-            GmmGen9ResourceULT.cpp

-            GmmResourceCpuBltULT.cpp

-            GmmResourceULT.cpp

-            )

-

-source_group("Header Files\\Cache Policy" FILES

-             GmmCachePolicyULT.h

-             GmmGen10CachePolicyULT.h

-             GmmGen11CachePolicyULT.h

-             GmmGen12CachePolicyULT.h

-             GmmGen9CachePolicyULT.h

-            )

-

-source_group("Header Files\\Resource" FILES

-             GmmGen12ResourceULT.h

-             GmmGen11ResourceULT.h

-             GmmGen10ResourceULT.h

-             GmmGen9ResourceULT.h

-             GmmResourceULT.h

-            )

-

-source_group("gtest" FILES

-            googletest/gtest/gtest.h

-            googletest/src/gtest-all.cc

-            )

-

-include_directories(BEFORE ./)

-

-include_directories(BEFORE ${PROJECT_SOURCE_DIR})

-

-include_directories(

-    googletest

-    googletest/gtest

-    ${BS_DIR_INC}/umKmInc

-    ${BS_DIR_INC}

-    ${BS_DIR_GMMLIB}/inc

-    ${BS_DIR_INC}/common

-    )

-

-macro(GmmLibULTSetTargetConfig ultTarget)

-	if (TARGET ${ultTarget})

-			set_property(TARGET ${ultTarget} APPEND PROPERTY COMPILE_DEFINITIONS

-				$<$<CONFIG:Release>: _RELEASE>

-				$<$<CONFIG:ReleaseInternal>: _RELEASE_INTERNAL>

-				$<$<CONFIG:Debug>: _DEBUG>

-			)

-		endif()

-

-endmacro()

-

-add_executable(${EXE_NAME} ${GMMULT_HEADERS} ${GMMULT_SOURCES})

-

-GmmLibULTSetTargetConfig(${EXE_NAME})

-

-set_property(TARGET ${EXE_NAME} APPEND PROPERTY COMPILE_DEFINITIONS __GMM GMM_LIB_DLL __UMD)

-

-if(NOT TARGET igfx_gmmumd_dll)

-    add_subdirectory("${BS_DIR_GMMLIB}" "${CMAKE_BINARY_DIR}/gmmlib/ult")

-endif()

-target_link_libraries(${EXE_NAME} igfx_gmmumd_dll)

-

-target_link_libraries(${EXE_NAME}

-    pthread

-    dl

-)

-

-add_custom_target(Run_ULT ALL DEPENDS GMMULT)

-

-add_custom_command(

-    TARGET Run_ULT

-    POST_BUILD

-    COMMAND echo running ULTs

-    COMMAND "${CMAKE_COMMAND}" -E env "LD_LIBRARY_PATH=$<TARGET_FILE_DIR:igfx_gmmumd_dll>" ${CMAKE_CFG_INTDIR}/${EXE_NAME} --gtest_filter=CTest*

-)
\ No newline at end of file
+# Copyright(c) 2017 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.
+
+set (EXE_NAME GMMULT)
+
+set(GMMULT_HEADERS
+     GmmCachePolicyULT.h
+     GmmCommonULT.h
+     GmmGen10CachePolicyULT.h
+     GmmGen10ResourceULT.h
+     GmmGen11CachePolicyULT.h
+     GmmGen11ResourceULT.h
+     GmmGen12ResourceULT.h
+     GmmGen12CachePolicyULT.h
+     GmmGen9CachePolicyULT.h
+     GmmGen9ResourceULT.h
+     GmmResourceULT.h
+     GmmAuxTableULT.h
+     stdafx.h
+     targetver.h
+     )
+
+set(GMMULT_SOURCES
+    GmmCachePolicyULT.cpp
+    GmmCommonULT.cpp
+    GmmGen10CachePolicyULT.cpp
+    GmmGen10ResourceULT.cpp
+    GmmGen11CachePolicyULT.cpp
+    GmmGen12CachePolicyULT.cpp
+    GmmGen11ResourceULT.cpp
+    GmmGen12ResourceULT.cpp
+    GmmGen9CachePolicyULT.cpp
+    GmmGen9ResourceULT.cpp
+    GmmResourceCpuBltULT.cpp
+    GmmResourceULT.cpp
+    GmmAuxTableULT.cpp
+    googletest/src/gtest-all.cc
+    GmmULT.cpp
+)
+
+source_group("Source Files\\Cache Policy" FILES
+            GmmCachePolicyULT.cpp
+            GmmGen9CachePolicyULT.cpp
+            GmmGen10CachePolicyULT.cpp
+            GmmGen11CachePolicyULT.cpp
+            GmmGen12CachePolicyULT.cpp
+            )
+
+source_group("Source Files\\Resource" FILES
+            GmmGen10ResourceULT.cpp
+            GmmGen11ResourceULT.cpp
+            GmmGen12ResourceULT.cpp
+
+            GmmGen9ResourceULT.cpp
+            GmmResourceCpuBltULT.cpp
+            GmmResourceULT.cpp
+            )
+
+source_group("Source Files\\TranslationTable" FILES
+            GmmAuxTableULT.cpp
+            )
+
+source_group("Header Files\\TranslationTable" FILES
+            GmmAuxTableULT.h
+            )
+
+source_group("Header Files\\Cache Policy" FILES
+             GmmCachePolicyULT.h
+             GmmGen10CachePolicyULT.h
+             GmmGen11CachePolicyULT.h
+             GmmGen12CachePolicyULT.h
+             GmmGen9CachePolicyULT.h
+            )
+
+source_group("Header Files\\Resource" FILES
+             GmmGen10ResourceULT.h
+             GmmGen11ResourceULT.h
+             GmmGen12ResourceULT.h
+             GmmGen9ResourceULT.h
+             GmmResourceULT.h
+            )
+
+source_group("gtest" FILES
+            googletest/gtest/gtest.h
+            googletest/src/gtest-all.cc
+            )
+
+include_directories(BEFORE ./)
+
+include_directories(BEFORE ${PROJECT_SOURCE_DIR})
+
+include_directories(
+    googletest
+    googletest/gtest
+    ${BS_DIR_INC}/umKmInc
+    ${BS_DIR_INC}
+    ${BS_DIR_GMMLIB}/inc
+    ${BS_DIR_INC}/common
+    )
+
+macro(GmmLibULTSetTargetConfig ultTarget)
+	if (TARGET ${ultTarget})
+			set_property(TARGET ${ultTarget} APPEND PROPERTY COMPILE_DEFINITIONS
+				$<$<CONFIG:Release>: _RELEASE>
+				$<$<CONFIG:ReleaseInternal>: _RELEASE_INTERNAL>
+				$<$<CONFIG:Debug>: _DEBUG>
+			)
+		endif()
+
+endmacro()
+
+add_executable(${EXE_NAME} ${GMMULT_HEADERS} ${GMMULT_SOURCES})
+
+GmmLibULTSetTargetConfig(${EXE_NAME})
+
+set_property(TARGET ${EXE_NAME} APPEND PROPERTY COMPILE_DEFINITIONS __GMM GMM_LIB_DLL __UMD)
+
+if(NOT TARGET igfx_gmmumd_dll)
+    add_subdirectory("${BS_DIR_GMMLIB}" "${CMAKE_BINARY_DIR}/gmmlib/ult")
+endif()
+target_link_libraries(${EXE_NAME} igfx_gmmumd_dll)
+
+target_link_libraries(${EXE_NAME}
+    pthread
+    dl
+)
+
+add_custom_target(Run_ULT ALL DEPENDS GMMULT)
+
+add_custom_command(
+    TARGET Run_ULT
+    POST_BUILD
+    COMMAND echo running ULTs
+    COMMAND "${CMAKE_COMMAND}" -E env "LD_LIBRARY_PATH=$<TARGET_FILE_DIR:igfx_gmmumd_dll>" ${CMAKE_CFG_INTDIR}/${EXE_NAME} --gtest_filter=CTest*
+)
diff --git a/Source/GmmLib/ULT/GmmAuxTableULT.cpp b/Source/GmmLib/ULT/GmmAuxTableULT.cpp
new file mode 100644
index 0000000..5bb8b81
--- /dev/null
+++ b/Source/GmmLib/ULT/GmmAuxTableULT.cpp
@@ -0,0 +1,265 @@
+/*==============================================================================
+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.
+============================================================================*/
+
+#ifdef __linux__
+
+#include "GmmAuxTableULT.h"
+
+using namespace std;
+using namespace GmmLib;
+
+static GMM_DEVICE_CALLBACKS_INT DeviceCBInt;
+
+CTestAuxTable::CTestAuxTable()
+{
+}
+
+CTestAuxTable::~CTestAuxTable()
+{
+}
+
+int CTestAuxTable::allocCB(void *bufMgr, size_t size, size_t alignment, void **bo, void **cpuAddr, uint64_t *gpuAddr)
+{
+    if(bufMgr != (void *)0xdeadbeef)
+        return -1;
+
+    if(!bo || !cpuAddr || !gpuAddr)
+        return -2;
+
+    *cpuAddr = aligned_alloc(alignment, ALIGN(size, alignment));
+    if(!*cpuAddr)
+        return -3;
+
+    *bo      = *cpuAddr;
+    *gpuAddr = (uint64_t)*cpuAddr;
+
+    return 0;
+}
+
+void CTestAuxTable::freeCB(void *bo)
+{
+    ASSERT_TRUE(bo != NULL);
+
+    free(bo);
+}
+
+void CTestAuxTable::waitFromCpuCB(void *bo)
+{
+}
+
+void CTestAuxTable::SetUpTestCase()
+{
+    GfxPlatform.eProductFamily    = IGFX_TIGERLAKE_LP;
+    GfxPlatform.eRenderCoreFamily = IGFX_GEN12_CORE;
+
+    DeviceCBInt.pBufMgr                   = (void *)0xdeadbeef;
+    DeviceCBInt.DevCbPtrs_.pfnAllocate    = CTestAuxTable::allocCB;
+    DeviceCBInt.DevCbPtrs_.pfnDeallocate  = CTestAuxTable::freeCB;
+    DeviceCBInt.DevCbPtrs_.pfnWaitFromCpu = CTestAuxTable::waitFromCpuCB;
+
+    if(GfxPlatform.eProductFamily == IGFX_UNKNOWN ||
+       GfxPlatform.eRenderCoreFamily == IGFX_UNKNOWN_CORE)
+    {
+        GfxPlatform.eProductFamily    = IGFX_BROADWELL;
+        GfxPlatform.eRenderCoreFamily = IGFX_GEN8_CORE;
+    }
+
+    AllocateAdapterInfo();
+    if(pGfxAdapterInfo)
+    {
+        pGfxAdapterInfo->SkuTable.FtrE2ECompression = true;
+        pGfxAdapterInfo->SkuTable.FtrLinearCCS      = true;
+    }
+
+    CommonULT::SetUpTestCase();
+}
+
+void CTestAuxTable::TearDownTestCase()
+{
+    CommonULT::TearDownTestCase();
+}
+
+TEST_F(CTestAuxTable, TestUpdateAuxTableCompressedSurface)
+{
+    GmmPageTableMgr *mgr = pGmmULTClientContext->CreatePageTblMgrObject(&DeviceCBInt, TT_TYPE::AUXTT);
+
+    ASSERT_TRUE(mgr != NULL);
+
+    Surface *surf = new Surface(7680, 4320);
+
+    ASSERT_TRUE(surf != NULL && surf->init());
+
+    GMM_DDI_UPDATEAUXTABLE updateReq = {0};
+
+    updateReq.BaseResInfo = surf->getGMMResourceInfo();
+    updateReq.BaseGpuVA   = surf->getGfxAddress(GMM_PLANE_Y);
+    updateReq.Map         = 1;
+
+    GMM_STATUS res = mgr->UpdateAuxTable(&updateReq);
+    ASSERT_TRUE(res == GMM_SUCCESS);
+
+    delete surf;
+    pGmmULTClientContext->DestroyPageTblMgrObject(mgr);
+}
+
+TEST_F(CTestAuxTable, DISABLED_TestUpdateAuxTableNonCompressedSurface)
+{
+    GmmPageTableMgr *mgr = pGmmULTClientContext->CreatePageTblMgrObject(&DeviceCBInt, TT_TYPE::AUXTT);
+
+    ASSERT_TRUE(mgr != NULL);
+
+    Surface *surf = new Surface(7680, 4320, false);
+
+    ASSERT_TRUE(surf != NULL && surf->init());
+
+    GMM_DDI_UPDATEAUXTABLE updateReq = {0};
+
+    memset(&updateReq, 0, sizeof(GMM_DDI_UPDATEAUXTABLE));
+
+    updateReq.BaseResInfo = surf->getGMMResourceInfo();
+    updateReq.BaseGpuVA   = surf->getGfxAddress(GMM_PLANE_Y);
+    updateReq.Map         = 1;
+
+    GMM_STATUS res = mgr->UpdateAuxTable(&updateReq);
+    ASSERT_TRUE(res != GMM_SUCCESS);
+
+    delete surf;
+    pGmmULTClientContext->DestroyPageTblMgrObject(mgr);
+}
+
+TEST_F(CTestAuxTable, TestInvalidateAuxTable)
+{
+    GmmPageTableMgr *mgr = pGmmULTClientContext->CreatePageTblMgrObject(&DeviceCBInt, TT_TYPE::AUXTT);
+
+    ASSERT_TRUE(mgr != NULL);
+
+    Surface *surf = new Surface(7680, 4320);
+
+    ASSERT_TRUE(surf != NULL && surf->init());
+
+    GMM_DDI_UPDATEAUXTABLE updateReq = {0};
+
+    updateReq.BaseResInfo = surf->getGMMResourceInfo();
+    updateReq.BaseGpuVA   = surf->getGfxAddress(GMM_PLANE_Y);
+    updateReq.Map         = 1;
+
+    GMM_STATUS res = mgr->UpdateAuxTable(&updateReq);
+    ASSERT_TRUE(res == GMM_SUCCESS);
+
+    memset(&updateReq, 0, sizeof(updateReq));
+
+    updateReq.BaseResInfo = surf->getGMMResourceInfo();
+    updateReq.Map         = 0;
+
+    res = mgr->UpdateAuxTable(&updateReq);
+    ASSERT_TRUE(res == GMM_SUCCESS);
+
+    delete surf;
+    pGmmULTClientContext->DestroyPageTblMgrObject(mgr);
+}
+
+TEST_F(CTestAuxTable, DISABLED_TestUpdateAuxTableStress)
+{
+    const int num_surf = 1000;
+    Surface * surfaces[num_surf];
+    Surface * surf;
+    int       i;
+
+    GmmPageTableMgr *mgr = pGmmULTClientContext->CreatePageTblMgrObject(&DeviceCBInt, TT_TYPE::AUXTT);
+
+    ASSERT_TRUE(mgr != NULL);
+
+    for(i = 0; i < num_surf; i++)
+    {
+        surf        = new Surface(7680, 4320);
+        surfaces[i] = surf;
+
+        ASSERT_TRUE(surf != NULL && surf->init());
+
+        GMM_DDI_UPDATEAUXTABLE updateReq = {0};
+
+        updateReq.BaseResInfo = surf->getGMMResourceInfo();
+        updateReq.BaseGpuVA   = surf->getGfxAddress(GMM_PLANE_Y);
+        updateReq.Map         = 1;
+
+        mgr->UpdateAuxTable(&updateReq);
+    }
+
+    for(i = 0; i < num_surf; i++)
+    {
+        surf = surfaces[i];
+        delete surf;
+    }
+
+    pGmmULTClientContext->DestroyPageTblMgrObject(mgr);
+}
+
+TEST_F(CTestAuxTable, TestAuxTableContent)
+{
+    GmmPageTableMgr *mgr = pGmmULTClientContext->CreatePageTblMgrObject(&DeviceCBInt, TT_TYPE::AUXTT);
+
+    ASSERT_TRUE(mgr != NULL);
+
+    Surface *surf = new Surface(720, 480);
+
+    ASSERT_TRUE(surf != NULL && surf->init());
+
+    GMM_DDI_UPDATEAUXTABLE updateReq = {0};
+
+    updateReq.BaseResInfo = surf->getGMMResourceInfo();
+    updateReq.BaseGpuVA   = surf->getGfxAddress(GMM_PLANE_Y);
+    updateReq.Map         = 1;
+
+    GMM_STATUS res = mgr->UpdateAuxTable(&updateReq);
+    ASSERT_TRUE(res == GMM_SUCCESS);
+
+    Walker *ywalker = new Walker(surf->getGfxAddress(GMM_PLANE_Y),
+                                 surf->getAuxGfxAddress(GMM_AUX_CCS),
+                                 mgr->GetAuxL3TableAddr());
+
+    for(size_t i = 0; i < surf->getSurfaceSize(GMM_PLANE_Y); i++)
+    {
+        GMM_GFX_ADDRESS addr     = surf->getGfxAddress(GMM_PLANE_Y) + i;
+        GMM_GFX_ADDRESS val      = ywalker->walk(addr);
+        GMM_GFX_ADDRESS expected = ywalker->expected(addr);
+        ASSERT_EQ(expected, val);
+    }
+
+    Walker *uvwalker = new Walker(surf->getGfxAddress(GMM_PLANE_U),
+                                  surf->getAuxGfxAddress(GMM_AUX_UV_CCS),
+                                  mgr->GetAuxL3TableAddr());
+
+    for(size_t i = 0; i < surf->getSurfaceSize(GMM_PLANE_U); i++)
+    {
+        GMM_GFX_ADDRESS addr     = surf->getGfxAddress(GMM_PLANE_U) + i;
+        GMM_GFX_ADDRESS val      = uvwalker->walk(addr);
+        GMM_GFX_ADDRESS expected = uvwalker->expected(addr);
+        ASSERT_EQ(expected, val);
+    }
+
+    delete uvwalker;
+    delete ywalker;
+    delete surf;
+    pGmmULTClientContext->DestroyPageTblMgrObject(mgr);
+}
+
+#endif /* __linux__ */
diff --git a/Source/GmmLib/ULT/GmmAuxTableULT.h b/Source/GmmLib/ULT/GmmAuxTableULT.h
new file mode 100644
index 0000000..3a40f1d
--- /dev/null
+++ b/Source/GmmLib/ULT/GmmAuxTableULT.h
@@ -0,0 +1,252 @@
+/*==============================================================================
+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.
+============================================================================*/
+
+#pragma once
+
+#ifdef __linux__
+
+#ifndef _ISOC11_SOURCE
+#define _ISOC11_SOURCE 1
+#endif
+
+#include "GmmGen10ResourceULT.h"
+#include <stdlib.h>
+#include <malloc.h>
+
+#ifndef ALIGN
+#define ALIGN(v, a) (((v) + ((a)-1)) & ~((a)-1))
+#endif
+
+class CTestAuxTable : public CTestGen10Resource
+{
+
+public:
+    static void SetUpTestCase();
+    static void TearDownTestCase();
+
+    CTestAuxTable();
+    ~CTestAuxTable();
+
+    static int  allocCB(void *bufMgr, size_t size, size_t alignment, void **bo, void **cpuAddr, uint64_t *gpuAddr);
+    static void freeCB(void *bo);
+    static void waitFromCpuCB(void *bo);
+
+    class Surface
+    {
+    public:
+        Surface(unsigned int width, unsigned int height, bool mmc = true)
+            : mWidth(width), mHeight(height), mMMC(mmc), mResInfo(0), mBuf(0)
+        {
+        }
+
+        ~Surface()
+        {
+            deinit();
+        }
+
+        bool init()
+        {
+            size_t size;
+            size_t alignment;
+
+            GMM_RESCREATE_PARAMS gmmParams       = {};
+            gmmParams.Type                       = RESOURCE_2D;
+            gmmParams.Format                     = GMM_FORMAT_NV12;
+            gmmParams.BaseWidth                  = mWidth;
+            gmmParams.BaseHeight                 = mHeight;
+            gmmParams.Depth                      = 0x1;
+            gmmParams.ArraySize                  = 1;
+            gmmParams.Flags.Info.TiledY          = 1;
+            gmmParams.Flags.Info.MediaCompressed = mMMC ? 1 : 0;
+            //gmmParams.Flags.Gpu.CCS               = mmc ? 1 : 0;
+            gmmParams.Flags.Gpu.MMC               = mMMC ? 1 : 0;
+            gmmParams.Flags.Gpu.Texture           = 1;
+            gmmParams.Flags.Gpu.RenderTarget      = 1;
+            gmmParams.Flags.Gpu.UnifiedAuxSurface = mMMC ? 1 : 0;
+            //gmmParams.Flags.Gpu.Depth             = 1;
+            gmmParams.Flags.Gpu.Video = true;
+
+            mResInfo = pGmmULTClientContext->CreateResInfoObject(&gmmParams);
+
+            size = mResInfo->GetSizeSurface();
+
+            alignment = mResInfo->GetResFlags().Info.TiledYf ? GMM_KBYTE(16) : GMM_KBYTE(64);
+
+            mBuf = aligned_alloc(alignment, ALIGN(size, alignment));
+
+            if(!mResInfo || !mBuf)
+                return false;
+
+            mYBase      = (GMM_GFX_ADDRESS)mBuf;
+            mUVBase     = 0;
+            mAuxYBase   = mYBase + mResInfo->GetUnifiedAuxSurfaceOffset(GMM_AUX_CCS);
+            mAuxUVBase  = 0;
+            mYPlaneSize = mResInfo->GetSizeMainSurface();
+
+            if(pGmmULTClientContext->IsPlanar(mResInfo->GetResourceFormat()))
+            {
+                GMM_REQ_OFFSET_INFO ReqInfo = {0};
+                ReqInfo.Plane               = GMM_PLANE_U;
+                ReqInfo.ReqRender           = 1;
+
+                mResInfo->GetOffset(ReqInfo);
+                mYPlaneSize = ReqInfo.Render.Offset64;
+
+                mUVBase    = mYBase + mYPlaneSize;
+                mAuxUVBase = mYBase + mResInfo->GetUnifiedAuxSurfaceOffset(GMM_AUX_UV_CCS);
+            }
+
+            mUVPlaneSize = mResInfo->GetSizeMainSurface() - mYPlaneSize;
+
+            return true;
+        }
+
+        void deinit()
+        {
+            if(mBuf)
+            {
+                free(mBuf);
+                mBuf = NULL;
+            }
+
+            if(mResInfo)
+            {
+                pGmmULTClientContext->DestroyResInfoObject(mResInfo);
+                mResInfo = NULL;
+            }
+        }
+
+        GMM_GFX_ADDRESS getGfxAddress(GMM_YUV_PLANE plane)
+        {
+            switch(plane)
+            {
+                case GMM_PLANE_Y:
+                    return mYBase;
+                case GMM_PLANE_U:
+                case GMM_PLANE_V:
+                    return mUVBase;
+                default:
+                    throw;
+            }
+        }
+
+        GMM_GFX_ADDRESS getAuxGfxAddress(GMM_UNIFIED_AUX_TYPE auxType)
+        {
+            switch(auxType)
+            {
+                case GMM_AUX_CCS:
+                case GMM_AUX_Y_CCS:
+                    return mAuxYBase;
+                case GMM_AUX_UV_CCS:
+                    return mAuxUVBase;
+                default:
+                    throw;
+            }
+        }
+
+        GMM_RESOURCE_INFO *getGMMResourceInfo()
+        {
+            return mResInfo;
+        }
+
+        size_t getSurfaceSize(GMM_YUV_PLANE plane)
+        {
+            switch(plane)
+            {
+                case GMM_PLANE_Y:
+                    return mYPlaneSize;
+                case GMM_PLANE_U:
+                case GMM_PLANE_V:
+                    return mUVPlaneSize;
+                default:
+                    throw;
+            }
+        }
+
+    private:
+        unsigned int       mWidth;
+        unsigned int       mHeight;
+        bool               mMMC;
+        GMM_RESOURCE_INFO *mResInfo;
+        void *             mBuf;
+        GMM_GFX_ADDRESS    mYBase;
+        GMM_GFX_ADDRESS    mUVBase;
+        GMM_GFX_ADDRESS    mAuxYBase;
+        GMM_GFX_ADDRESS    mAuxUVBase;
+        size_t             mYPlaneSize;
+        size_t             mUVPlaneSize;
+    };
+
+    class Walker
+    {
+    public:
+        Walker(GMM_GFX_ADDRESS mainBase, GMM_GFX_ADDRESS auxBase,
+               GMM_GFX_ADDRESS l3Base)
+        {
+            mMainBase = mainBase;
+            mAuxBase  = (auxBase >> 6) << 6;
+            mL3Base   = (uint64_t *)l3Base;
+        }
+
+        GMM_GFX_ADDRESS expected(GMM_GFX_ADDRESS addr)
+        {
+            uint8_t  Is64KChunk = (const_cast<WA_TABLE &>(pGfxAdapterInfo->WaTable).WaAuxTable16KGranular) ? 0 : 1;
+            uint32_t count      = (addr - mMainBase) / (Is64KChunk ? GMM_KBYTE(64) : GMM_KBYTE(16));
+            return mAuxBase + (Is64KChunk ? 256 : 64) * count;
+        }
+
+        GMM_GFX_ADDRESS walk(GMM_GFX_ADDRESS addr)
+        {
+            uint64_t  mask   = (const_cast<WA_TABLE &>(pGfxAdapterInfo->WaTable).WaAuxTable16KGranular) ? 0x0000ffffffffffc0 : 0x0000ffffffffff00;
+            uint32_t  idx    = l3Index(addr);
+            uint64_t *l2Base = (uint64_t *)((mL3Base[idx] >> 15) << 15);
+            idx              = l2Index(addr);
+            uint64_t *l1Base = (uint64_t *)((l2Base[idx] >> 13) << 13);
+            idx              = l1Index(addr);
+            uint64_t auxAddr = (uint64_t)(l1Base[idx] & mask);
+            return auxAddr;
+        }
+
+    public:
+        static inline uint32_t l3Index(GMM_GFX_ADDRESS addr)
+        {
+            return GMM_AUX_L3_ENTRY_IDX(addr);
+        }
+
+        static inline uint32_t l2Index(GMM_GFX_ADDRESS addr)
+        {
+            return GMM_AUX_L2_ENTRY_IDX(addr);
+        }
+
+        static inline uint32_t l1Index(GMM_GFX_ADDRESS addr)
+        {
+            return GMM_AUX_L1_ENTRY_IDX_EXPORTED(addr, !(const_cast<WA_TABLE &>(pGfxAdapterInfo->WaTable).WaAuxTable16KGranular));
+        }
+
+    private:
+        GMM_GFX_ADDRESS mMainBase;
+        GMM_GFX_ADDRESS mAuxBase;
+        uint64_t *      mL3Base;
+    };
+};
+
+#endif /* __linux__ */
diff --git a/Source/GmmLib/ULT/GmmCommonULT.cpp b/Source/GmmLib/ULT/GmmCommonULT.cpp
index d3eaef7..0498c78 100644
--- a/Source/GmmLib/ULT/GmmCommonULT.cpp
+++ b/Source/GmmLib/ULT/GmmCommonULT.cpp
@@ -25,6 +25,7 @@
 #include <dlfcn.h>
 #endif
 
+
 ADAPTER_INFO *      CommonULT::pGfxAdapterInfo      = NULL;
 PLATFORM            CommonULT::GfxPlatform          = {};
 GMM_CLIENT_CONTEXT *CommonULT::pGmmULTClientContext = NULL;
diff --git a/Source/GmmLib/ULT/stdafx.h b/Source/GmmLib/ULT/stdafx.h
index 9a89212..717b5b9 100644
--- a/Source/GmmLib/ULT/stdafx.h
+++ b/Source/GmmLib/ULT/stdafx.h
@@ -59,6 +59,7 @@
 #include "../inc/External/Common/GmmInfoExt.h"
 #include "../inc/External/Common/GmmInfo.h"
 #include "../inc/External/Common/GmmClientContext.h"
+#include "../inc/External/Common/GmmPageTableMgr.h"
 #include "../inc/External/Common/GmmLibDll.h"
 #include "../inc/External/Common/GmmLibDllName.h"
 
diff --git a/Source/GmmLib/inc/External/Common/GmmClientContext.h b/Source/GmmLib/inc/External/Common/GmmClientContext.h
index 47f2ff2..8dcca1f 100644
--- a/Source/GmmLib/inc/External/Common/GmmClientContext.h
+++ b/Source/GmmLib/inc/External/Common/GmmClientContext.h
@@ -122,7 +122,7 @@
         GMM_VIRTUAL GMM_RESOURCE_INFO* GMM_STDCALL       CopyResInfoObject(GMM_RESOURCE_INFO *pSrcRes);
         GMM_VIRTUAL void GMM_STDCALL                     ResMemcpy(void *pDst, void *pSrc);
         GMM_VIRTUAL void  GMM_STDCALL                    DestroyResInfoObject(GMM_RESOURCE_INFO    *pResInfo);
-
+        
 #ifdef GMM_LIB_DLL
         /* ResourceInfo and PageTableMgr Create and Destroy APIs with Client provided Memory Allocators */
         GMM_VIRTUAL GMM_RESOURCE_INFO* GMM_STDCALL       CreateResInfoObject(GMM_RESCREATE_PARAMS *pCreateParams,
@@ -130,6 +130,18 @@
         GMM_VIRTUAL void  GMM_STDCALL                    DestroyResInfoObject(GMM_RESOURCE_INFO    *pResInfo,
                                                                               GmmClientAllocationCallbacks *pAllocCbs);
 #endif
+         
+        /* PageTableMgr Creation and Destroy API's */
+        GMM_VIRTUAL GMM_PAGETABLE_MGR*  GMM_STDCALL      CreatePageTblMgrObject(GMM_DEVICE_CALLBACKS_INT *pDevCb, uint32_t TTFlags);
+        /* PageTableMgr Creation and Destroy API's */
+        GMM_VIRTUAL void GMM_STDCALL                    DestroyPageTblMgrObject(GMM_PAGETABLE_MGR    *pPageTableMgr);
+        
+        GMM_VIRTUAL GMM_PAGETABLE_MGR* GMM_STDCALL      CreatePageTblMgrObject(
+                                                        GMM_DEVICE_CALLBACKS_INT* pDevCb,
+                                                        uint32_t TTFlags,
+                                                        GmmClientAllocationCallbacks* pAllocCbs);
+        GMM_VIRTUAL void GMM_STDCALL                    DestroyPageTblMgrObject(GMM_PAGETABLE_MGR* pPageTableMgr,
+                                                        GmmClientAllocationCallbacks* pAllocCbs);
     };
 }
 
diff --git a/Source/GmmLib/inc/External/Common/GmmCommonExt.h b/Source/GmmLib/inc/External/Common/GmmCommonExt.h
index d0b7c1e..689ddab 100644
--- a/Source/GmmLib/inc/External/Common/GmmCommonExt.h
+++ b/Source/GmmLib/inc/External/Common/GmmCommonExt.h
@@ -72,6 +72,10 @@
 #define GMM_NO_FENCE_REG        0xDEADBEEF
 #define GMM_MAX_DISPLAYS        3
 
+#if defined __linux__
+typedef void* HANDLE;
+#endif
+
 //===========================================================================
 // typedef:
 //      GMM_GFX_ADDRESS/etc.
diff --git a/Source/GmmLib/inc/External/Common/GmmHw.h b/Source/GmmLib/inc/External/Common/GmmHw.h
new file mode 100644
index 0000000..81b4cf6
--- /dev/null
+++ b/Source/GmmLib/inc/External/Common/GmmHw.h
@@ -0,0 +1,150 @@
+/*==============================================================================
+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.
+============================================================================*/
+
+
+#pragma once
+#include "gfxmacro.h"
+
+
+
+////////////////////// Auxiliary Translation Table definitions//////////////////////////////////////////
+//===========================================================================
+// typedef:
+//        GMM_AUXTTL3e
+//
+// Description:
+//        Struct for Auxiliary Translation-Table L3 entry
+//--------------------------------------------------------------------------
+typedef union GMM_AUXTTL3e_REC
+{
+    struct {
+        uint64_t Valid     :  1;
+        uint64_t Reserved0 : 14;
+        uint64_t L2GfxAddr : 33;
+        uint64_t Reserved1 : 16;
+    };
+    uint64_t Value;
+} GMM_AUXTTL3e;
+C_ASSERT(sizeof(GMM_AUXTTL3e) == 8);
+
+// Get the L2GfxAddr bit field as a full L2 graphics address
+#define GMM_FULL_GFXADDR_FROM_AUX_L3e_L2GFXADDR(L2GfxAddr) ((L2GfxAddr) << 16)
+
+// Set the L2GfxAddr bit field given a full L2 graphics address
+#define GMM_TO_AUX_L3e_L2GFXADDR(L2GfxAddress) ((L2GfxAddress) >> 16)
+
+//===========================================================================
+// typedef:
+//        GMM_AUXTTL2e
+//
+// Description:
+//        Struct for Auxiliary Translation-Table L2 entry
+//--------------------------------------------------------------------------
+typedef union GMM_AUXTTL2e_REC
+{
+    struct
+    {
+        uint64_t Valid     :  1;
+        uint64_t Reserved0 : 12;
+        uint64_t L1GfxAddr : 35;
+        uint64_t Reserved1 : 16;
+    };
+    uint64_t Value;
+} GMM_AUXTTL2e;
+C_ASSERT(sizeof(GMM_AUXTTL2e) == 8);
+
+// Get the L1GfxAddr bit field as a full L1 graphics address
+#define GMM_FULL_GFXADDR_FROM_AUX_L2e_L1GFXADDR(L1GfxAddr) ((L1GfxAddr) << 16)
+
+// Set the L1GfxAddr bit field given a full L1 graphics address
+#define GMM_TO_AUX_L2e_L1GFXADDR(L1GfxAddress) ((L1GfxAddress) >> 16)
+
+typedef union GMM_AUXTTL1e_REC
+{
+    struct
+    {
+        uint64_t Valid      :  1;
+        uint64_t Mode       :  2;      //Compression ratio (128B compr ie 2:1 for RC, 256B compr ie 4:n compr for MC)
+        uint64_t Lossy      :  1;      //Lossy Compression
+        uint64_t Reserved0  :  2;
+        uint64_t Reserved2  :  2;      //LSbs of 64B-aligned CCS chunk/cacheline address
+        uint64_t GfxAddress : 40;      //256B-aligned CCS chunk address
+        uint64_t Reserved1  :  4;
+        uint64_t TileMode   :  2;      //Ys = 0, Y=1,  Reserved=(2-3)
+        uint64_t Depth      :  3;      //Packed/Planar bit-depth for MC; Bpp for RC
+        uint64_t LumaChroma :  1;      //Planar Y=0 or Cr=1
+        uint64_t Format     :  6;      //Format encoding shared with Vivante/Internal CC/DEC units to recognize surafce formats
+    };
+    uint64_t Value;
+} GMM_AUXTTL1e;
+C_ASSERT(sizeof(GMM_AUXTTL1e) == 8);
+
+#define GMM_NO_TABLE            ((GMM_GFX_ADDRESS)(-1L))                 //common
+
+#define GMM_INVALID_AUX_ENTRY      ~__BIT(0)
+
+#define GMM_AUX_L1e_SIZE        (sizeof(GMM_AUXTTL1e))
+#define GMM_AUX_L2e_SIZE        (sizeof(GMM_AUXTTL2e))
+#define GMM_AUX_L3e_SIZE        (sizeof(GMM_AUXTTL3e))
+
+#define GMM_AUX_L1_LOW_BIT      (14)
+#define GMM_AUX_L1_HIGH_BIT     (23)
+#define GMM_AUX_L2_LOW_BIT      (24)
+#define GMM_AUX_L2_HIGH_BIT     (35)
+#define GMM_AUX_L3_LOW_BIT      (36)
+#define GMM_AUX_L3_HIGH_BIT     (47)
+
+//For perf, AuxTable granularity changed to 64K
+#define WA16K                   (pGmmGlobalContext->GetWaTable().WaAuxTable16KGranular)
+
+// #L1 entries, i.e. 1024; 16K-granular ie 4 consequtive pages share Aux-cacheline;
+// HW only tracks the distinct entries;
+// Handle WA where HW chicken bit forces 64K-granularity
+#define GMM_AUX_L1_SIZE(pGmmGlobalContext)         ((1 << (GMM_AUX_L1_HIGH_BIT - GMM_AUX_L1_LOW_BIT + 1)) / (!(WA16K) ? 4 : 1))
+#define GMM_AUX_L1_SIZE_DWORD(pGmmGlobalContext)   (GFX_CEIL_DIV(GMM_AUX_L1_SIZE(pGmmGlobalContext), 32))
+
+// #L2 entries, i.e. 4096
+#define GMM_AUX_L2_SIZE         (1 << (GMM_AUX_L2_HIGH_BIT - GMM_AUX_L2_LOW_BIT + 1))
+#define GMM_AUX_L2_SIZE_DWORD   (GFX_CEIL_DIV(GMM_AUX_L2_SIZE, 32))
+
+// #L3 entries, i.e. 4096
+#define GMM_AUX_L3_SIZE         (1 << (GMM_AUX_L3_HIGH_BIT - GMM_AUX_L3_LOW_BIT + 1))
+
+#define GMM_AUX_L1_ENTRY_IDX(GfxAddress,pGmmGlobalContext)                                         \
+    ((((GfxAddress) & GFX_MASK_LARGE(GMM_AUX_L1_LOW_BIT, GMM_AUX_L1_HIGH_BIT)) >> \
+     (uint64_t)GMM_AUX_L1_LOW_BIT) / (!(WA16K) ? 4 : 1))
+
+
+#define GMM_AUX_L1_ENTRY_IDX_EXPORTED(GfxAddress,WA64KEx)                         \
+    ((((GfxAddress) & GFX_MASK_LARGE(GMM_AUX_L1_LOW_BIT, GMM_AUX_L1_HIGH_BIT)) >> \
+     (uint64_t)GMM_AUX_L1_LOW_BIT) / ((WA64KEx) ? 4 : 1))
+
+
+#define GMM_AUX_L2_ENTRY_IDX(GfxAddress)                                     \
+    (((GfxAddress) & GFX_MASK_LARGE(GMM_AUX_L2_LOW_BIT, GMM_AUX_L2_HIGH_BIT)) >> \
+    (uint64_t)GMM_AUX_L2_LOW_BIT)
+
+#define GMM_AUX_L3_ENTRY_IDX(GfxAddress)                                     \
+    (((GfxAddress) & GFX_MASK_LARGE(GMM_AUX_L3_LOW_BIT, GMM_AUX_L3_HIGH_BIT)) >> \
+    (uint64_t)GMM_AUX_L3_LOW_BIT)
+
+////////////////////// Auxiliary Translation Table definitions end//////////////////////////////////////////
diff --git a/Source/GmmLib/inc/External/Common/GmmPageTableMgr.h b/Source/GmmLib/inc/External/Common/GmmPageTableMgr.h
new file mode 100644
index 0000000..bc73f00
--- /dev/null
+++ b/Source/GmmLib/inc/External/Common/GmmPageTableMgr.h
@@ -0,0 +1,165 @@
+/*==============================================================================
+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 GmmPageTableMgr
+             for user-mode PageTable management, that is common for both 
+             Linux and Windows.
+
+============================================================================*/
+
+#pragma once
+#include "GmmHw.h"
+
+#ifdef __linux__
+#include <pthread.h>
+#endif
+
+typedef enum _GMM_ENGINE_TYPE
+{
+    ENGINE_TYPE_RCS = 0,            //RCS
+    ENGINE_TYPE_COMPUTE = 1,        //Compute-CS
+    ENGINE_TYPE_BCS,                //BLT
+    ENGINE_TYPE_VD0,
+    ENGINE_TYPE_VD1,
+    ENGINE_TYPE_VE0
+    //Add all engines supporting  AUX-TT
+} GMM_ENGINE_TYPE;
+
+typedef enum TT_Flags
+{
+    AUXTT = 1,              //Indicate TT request for AUX i.e. e2e compression
+} TT_TYPE;
+
+
+#if !(defined(__GMM_KMD__))
+// Shared Structure for both Windows and Linux
+typedef struct __GMM_DDI_UPDATEAUXTABLE
+{
+    GMM_UMD_SYNCCONTEXT * UmdContext;     // [in]  pointer to thread-specific data, specifying BBQHandle/Fence etc
+    GMM_RESOURCE_INFO * BaseResInfo;      // [in]  GmmResourceInfo ptr for compressed resource
+    GMM_RESOURCE_INFO * AuxResInfo;       // [in]  GmmResourceInfo ptr for separate Auxiliary resource
+    GMM_GFX_ADDRESS BaseGpuVA;            // [in]  GPUVA where compressed resource has been mapped
+    GMM_GFX_ADDRESS AuxSurfVA;            // [in]  GPUVA where separate Auxiliary resource has been mapped
+    uint8_t Map;                          // [in]  specifies if resource is being mapped or unmapped
+    uint8_t DoNotWait;                    // [in]  specifies if PageTable update be done on CPU (true) or GPU (false)
+}GMM_DDI_UPDATEAUXTABLE;
+
+#ifdef __cplusplus
+#include "GmmMemAllocator.hpp"
+
+namespace GmmLib
+{
+    class SyncInfoLin {                       //dummy class
+    public:
+        HANDLE BBQueueHandle;
+        uint64_t BBFence;
+        SyncInfoLin() {}
+        SyncInfoLin(HANDLE Handle, uint64_t Fence) {}
+    };
+    typedef class SyncInfoLin  SyncInfo;
+
+
+     //Forward class declarations
+     class AuxTable;
+     class GmmPageTablePool;
+     typedef class GmmPageTablePool GMM_PAGETABLEPool;
+
+     typedef enum POOL_TYPE_REC
+     {
+         POOL_TYPE_TRTTL1  = 0,
+         POOL_TYPE_TRTTL2  = 1,
+         POOL_TYPE_AUXTTL1 = 2,
+         POOL_TYPE_AUXTTL2 = 3,
+     } POOL_TYPE;
+
+    //////////////////////////////////////////////////////////////////////////////////////////////
+    /// Contains functions and members for GMM_PAGETABLE_MGR, clients must place its pointer in
+    /// their device object. Clients call GmmLib to initialize the instance and use it for mapping
+    /// /unmapping on GmmLib managed page tables (TR-TT for SparseResources, AUX-TT for compression)
+    //////////////////////////////////////////////////////////////////////////////////////////////
+    class GMM_LIB_API NON_PAGED_SECTION GmmPageTableMgr :
+                     public GmmMemAllocator
+    {
+    private:
+        GMM_ENGINE_TYPE EngType;             //PageTable managed @ device-level (specifies engine associated with the device)
+
+        AuxTable* AuxTTObj;                  //Auxiliary Translation Table obj
+
+        GMM_PAGETABLEPool *pPool;            //Common page table pool
+        uint32_t NumNodePoolElements;
+        GmmClientContext    *pClientContext;    ///< ClientContext of the client creating this Object
+
+         //OS-specific defn
+#if defined  __linux__
+	pthread_mutex_t PoolLock;
+#endif
+    public:
+        GMM_DEVICE_CALLBACKS DeviceCb;       //OS-specific defn: Will be used by Clients to send as input arguments for TR-TT APIs
+        GMM_DEVICE_CALLBACKS_INT DeviceCbInt;       //OS-specific defn: Will be used internally GMM lib
+        GMM_TRANSLATIONTABLE_CALLBACKS TTCb; //OS-specific defn
+        HANDLE hCsr;  // OCL per-device command stream receiver handle for aubcapture
+    public:
+        GmmPageTableMgr();
+        GmmPageTableMgr(GMM_DEVICE_CALLBACKS_INT *, uint32_t TTFlags, GmmClientContext  *pClientContextIn); // Allocates memory for indicate TT’s root-tables, initializes common node-pool
+        
+        
+        //GMM_VIRTUAL GMM_GFX_ADDRESS GetTRL3TableAddr();
+        GMM_VIRTUAL GMM_GFX_ADDRESS GetAuxL3TableAddr();
+
+        //Update TT root table address in context-image
+        GMM_VIRTUAL GMM_STATUS InitContextAuxTableRegister(HANDLE initialBBHandle, GMM_ENGINE_TYPE engType); //Clients call it to update Aux-Table pointer in context-image, engType reqd. if @ context level
+
+        //Aux TT management API
+        GMM_VIRTUAL GMM_STATUS UpdateAuxTable(const GMM_DDI_UPDATEAUXTABLE*);      //new API for updating Aux-Table to point to correct 16B-chunk
+                                                                       //for given host page VA  when base/Aux surf is mapped/unmapped
+        GMM_VIRTUAL void __ReleaseUnusedPool(GMM_UMD_SYNCCONTEXT *UmdContext);
+        GMM_VIRTUAL GMM_PAGETABLEPool * __GetFreePoolNode(uint32_t * FreePoolNodeIdx, POOL_TYPE PoolType);
+
+
+#if defined __linux__
+        //returns number of BOs for indicated TTs = NumNodePoolElements+1 BOs for root table and pools
+        GMM_VIRTUAL int GetNumOfPageTableBOs(uint8_t TTFlags);
+        //returns BO* list for indicated TT in client allocated memory
+        GMM_VIRTUAL int GetPageTableBOList(uint8_t TTFlags, void* BOList);
+#endif
+
+        //Destructor
+        GMM_VIRTUAL ~GmmPageTableMgr();                         //Clean-up page table structures
+
+        // Inline Functions
+        /////////////////////////////////////////////////////////////////////////////////////
+        /// Returns GmmClientContext associated with this PageTableMgr
+        /// @return ::GmmClientContext
+        /////////////////////////////////////////////////////////////////////////////////////
+        GMM_INLINE_VIRTUAL GmmClientContext* GetClientContext()
+        {
+            return pClientContext;
+        }
+
+    private:
+        GMM_PAGETABLEPool * __AllocateNodePool(uint32_t AddrAlignment, POOL_TYPE Type);
+
+    };
+
+    
+}
+#endif  // #ifdef __cplusplus
+#endif
diff --git a/Source/GmmLib/inc/External/Common/GmmResourceInfo.h b/Source/GmmLib/inc/External/Common/GmmResourceInfo.h
index 7c49411..972e4cf 100644
--- a/Source/GmmLib/inc/External/Common/GmmResourceInfo.h
+++ b/Source/GmmLib/inc/External/Common/GmmResourceInfo.h
@@ -100,4 +100,5 @@
 
 #ifdef __cplusplus
 }
-#endif /*__cplusplus*/
\ No newline at end of file
+#endif /*__cplusplus*/
+
diff --git a/Source/GmmLib/inc/External/Common/GmmResourceInfoCommon.h b/Source/GmmLib/inc/External/Common/GmmResourceInfoCommon.h
index 5c96507..0966d89 100644
--- a/Source/GmmLib/inc/External/Common/GmmResourceInfoCommon.h
+++ b/Source/GmmLib/inc/External/Common/GmmResourceInfoCommon.h
@@ -90,6 +90,28 @@
             GMM_VIRTUAL bool                ReAdjustPlaneProperties(bool IsAuxSurf);
             GMM_VIRTUAL const GMM_PLATFORM_INFO& GetPlatformInfo();
 
+            /////////////////////////////////////////////////////////////////////////////////////
+            /// Returns tile mode for SURFACE_STATE programming.
+            /// @return     Tiled Mode
+            /////////////////////////////////////////////////////////////////////////////////////
+            GMM_INLINE uint32_t GetTileModeSurfaceState(const GMM_TEXTURE_INFO *pTextureInfo) const
+            {
+                uint32_t TiledMode = 0;
+
+                if(GMM_IS_TILEY)
+                {
+                    TiledMode =
+                        pTextureInfo->Flags.Info.Linear ? 0 :
+                            pTextureInfo->Flags.Info.TiledW ? 1 :
+                            pTextureInfo->Flags.Info.TiledX ? 2 :
+                            /* Y/YF/YS */ 3;
+
+                    __GMM_ASSERT((TiledMode != 3) || (pTextureInfo->Flags.Info.TiledY || pTextureInfo->Flags.Info.TiledYf || pTextureInfo->Flags.Info.TiledYs));
+                }
+
+                return TiledMode;
+            }
+
     public:
             /* Constructors */
             GmmResourceInfoCommon():
@@ -138,6 +160,7 @@
                 ClientType          = rhs.ClientType;
                 Surf                = rhs.Surf;
                 AuxSurf             = rhs.AuxSurf;
+                AuxSecSurf          = rhs.AuxSecSurf;
                 RotateInfo          = rhs.RotateInfo;
                 ExistingSysMem      = rhs.ExistingSysMem;
                 SvmAddress          = rhs.SvmAddress;
@@ -1292,12 +1315,15 @@
                     }
                     else
                     {
-                        switch (GetHAlign())
+                        if(GMM_IS_TILEY)
                         {
-                            case 4:  HAlign = 1; break;
-                            case 8:  HAlign = 2; break;
-                            case 16: HAlign = 3; break;
-                            default: HAlign = 1;
+                            switch (GetHAlign())
+                            {
+                                case 4:  HAlign = 1; break;
+                                case 8:  HAlign = 2; break;
+                                case 16: HAlign = 3; break;
+                                default: HAlign = 1; // TODO(Benign): Change back to 0 + assert after packed YUV handling corrected.
+                            }
                         }
                     }
                 }
@@ -1362,16 +1388,16 @@
             /////////////////////////////////////////////////////////////////////////////////////
             GMM_INLINE_VIRTUAL GMM_INLINE_EXPORTED uint32_t GMM_STDCALL GetTileModeSurfaceState()
             {
-                uint32_t   TiledMode = 0;
-
-                TiledMode =
-                    Surf.Flags.Info.Linear ? 0 :
-                        Surf.Flags.Info.TiledX ? 2 :
-                        /* Y/YF/YS */       3;
-
-                __GMM_ASSERT((TiledMode != 3) || (Surf.Flags.Info.TiledY || Surf.Flags.Info.TiledYf || Surf.Flags.Info.TiledYs));
-
-                return TiledMode;
+                return GetTileModeSurfaceState(&Surf);
+			}
+			
+			/////////////////////////////////////////////////////////////////////////////////////
+            /// Returns tile mode for AUX SURFACE_STATE programming.
+            /// @return     Tiled Mode
+            /////////////////////////////////////////////////////////////////////////////////////
+            GMM_INLINE_VIRTUAL GMM_INLINE_EXPORTED uint32_t GMM_STDCALL GetAuxTileModeSurfaceState()
+            {
+                return GetTileModeSurfaceState(&AuxSurf);
             }
 
             /////////////////////////////////////////////////////////////////////////////////////
diff --git a/Source/GmmLib/inc/External/Common/GmmResourceInfoExt.h b/Source/GmmLib/inc/External/Common/GmmResourceInfoExt.h
index 9b8098f..63fbd98 100644
--- a/Source/GmmLib/inc/External/Common/GmmResourceInfoExt.h
+++ b/Source/GmmLib/inc/External/Common/GmmResourceInfoExt.h
@@ -181,7 +181,9 @@
 // TBD - Place holder for GMM_RESOURCE_FLAG definition.
 //---------------------------------------------------------------------------
 #include "GmmResourceFlags.h"
-
+#if defined __linux__
+    #include "External/Linux/GmmResourceInfoLinExt.h"
+#endif
 
 //==========================================================================
 // typedef:
diff --git a/Source/GmmLib/inc/External/Linux/GmmResourceInfoLinExt.h b/Source/GmmLib/inc/External/Linux/GmmResourceInfoLinExt.h
new file mode 100644
index 0000000..20d3b95
--- /dev/null
+++ b/Source/GmmLib/inc/External/Linux/GmmResourceInfoLinExt.h
@@ -0,0 +1,96 @@
+/*==============================================================================
+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.
+============================================================================*/
+#pragma once
+
+#ifdef __linux__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /*__cplusplus*/
+
+typedef struct {
+    int(*pfnAllocate)(void *bufMgr, size_t size, size_t alignment, void **bo, void **cpuAddr, uint64_t *gpuAddr);
+    void(*pfnDeallocate)(void *bo);
+    void(*pfnWaitFromCpu)(void *bo);;
+} GMM_DEVICE_CB_PTRS;
+
+typedef struct _GMM_DEVICE_CALLBACKS_INT
+{
+    void *pBufMgr;
+    GMM_DEVICE_CB_PTRS DevCbPtrs_;
+} GMM_DEVICE_CALLBACKS_INT;
+
+
+// Add the definition to compatible.
+typedef struct GMM_TRANSLATIONTABLE_CALLBACKS_REC
+{
+    int (*pfPrologTranslationTable)(void *pDeviceHandle);
+
+    int (*pfWriteL1Entries)(void *pDeviceHandle,
+                            const uint32_t NumEntries,
+                            GMM_GFX_ADDRESS GfxAddress,
+                            uint32_t *Data);
+
+    int (*pfWriteL2L3Entry)(void *pDeviceHandle,
+                            GMM_GFX_ADDRESS GfxAddress,
+                            uint64_t Data);
+
+    int (*pfWriteFenceID)(void *pDeviceHandle,
+                          GMM_GFX_ADDRESS GfxAddress,
+                          uint64_t Data);
+
+    int (*pfEpilogTranslationTable)(void *pDeviceHandle,
+                                    uint8_t ForceFlush);
+
+    int (*pfCopyL1Entry)(void *pDeviceHandle,
+                         GMM_GFX_ADDRESS DstGfxAddress,
+                         GMM_GFX_ADDRESS SrcGfxAddress);
+
+    int (*pfWriteL3Adr)(void *pDeviceHandle,
+                        GMM_GFX_ADDRESS L3GfxAddress,
+                        uint64_t RegOffset);
+} GMM_TRANSLATIONTABLE_CALLBACKS;
+
+typedef struct _GMM_DEVICE_CALLBACKS
+{
+    void *pBufferMgr;
+    int FuncDevice;
+    int(*pfnAllocate)(void *bufMgr, size_t size, size_t alignment, void **bo, void **cpuAddr, uint64_t *gpuAddr);
+    void(*pfnDeallocate)(void *bo);
+    void(*pfnWaitFromCpu)(void *bo);;
+} GMM_DEVICE_CALLBACKS;
+
+
+// This definition is only for code sharing.
+typedef struct GMM_UMD_SYNCCONTEXT_REC
+{
+    void                *pCommandQueueHandle;   // pointer to command queue handle
+    void                *pUpdateGpuVaInfo;
+    HANDLE              BBFenceObj;             // BatchBuffer Last Fence, for CPU to wait on before destroying TT pages
+    uint64_t            BBLastFence;            // BatchBuffer Last Fence for TT
+} GMM_UMD_SYNCCONTEXT;
+
+#ifdef __cplusplus
+}
+#endif /*__cplusplus*/
+
+#endif /*__linux__*/
diff --git a/Source/GmmLib/inc/Internal/Common/GmmLibInc.h b/Source/GmmLib/inc/Internal/Common/GmmLibInc.h
index a66365b..9f7d9e5 100644
--- a/Source/GmmLib/inc/Internal/Common/GmmLibInc.h
+++ b/Source/GmmLib/inc/Internal/Common/GmmLibInc.h
@@ -29,6 +29,7 @@
 
 #include "External/Common/GmmConst.h"
 #include "External/Common/GmmUtil.h"
+#include "External/Common/GmmHw.h"
 
 #include "External/Common/GmmCommonExt.h"
 #include "External/Common/GmmPlatformExt.h"
@@ -58,6 +59,7 @@
 #include "External/Common/GmmInfoExt.h"
 #include "External/Common/GmmInfo.h"
 #include "../Utility/GmmUtility.h"
+#include "External/Common/GmmPageTableMgr.h"
 
 #include "External/Common/GmmDebug.h"                   // Unified Definitions of GMM_ASSERT and GMM_DEBUG Macros
 
diff --git a/Source/GmmLib/inc/Internal/Linux/GmmResourceInfoLinInt.h b/Source/GmmLib/inc/Internal/Linux/GmmResourceInfoLinInt.h
new file mode 100644
index 0000000..750d537
--- /dev/null
+++ b/Source/GmmLib/inc/Internal/Linux/GmmResourceInfoLinInt.h
@@ -0,0 +1,71 @@
+/*==============================================================================
+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.
+============================================================================*/
+
+#pragma once
+
+#if defined(__linux__) && !LHDM
+
+// GMM Lib Client Exports
+#include "External/Common/GmmCommonExt.h"
+#include "External/Common/GmmUtil.h"
+#include "External/Common/GmmResourceFlags.h"
+#include "External/Common/GmmCachePolicy.h"
+#include "External/Common/GmmCachePolicyExt.h"
+#include "External/Common/GmmResourceInfoExt.h"
+#include "External/Common/GmmPlatformExt.h"
+#include "External/Common/GmmTextureExt.h"
+#include "External/Common/GmmInfoExt.h"
+#include "External/Common/GmmResourceInfo.h"
+#include "External/Common/GmmInfo.h"
+
+typedef struct {
+    size_t size;
+    size_t alignment;
+    void *bo;
+    void *cpuAddr;
+    uint64_t gfxAddr;
+} GMM_DDI_ALLOCATE;
+
+typedef struct  {
+    void *bo;
+} GMM_DDI_DEALLOCATE;
+
+typedef struct {
+    void *bo;
+}GMM_DDI_WAITFORSYNCHRONIZATIONOBJECTFROMCPU;
+
+typedef enum GMM_DEVICE_CALLBACKS_TYPE_REC
+{
+    GMM_DEV_CB_ALLOC = 0,
+    GMM_DEV_CB_DEALLOC,
+    GMM_DEV_CB_WAIT_FROM_CPU,
+} GMM_DEVICE_CALLBACKS_TYPE;
+
+int GmmDeviceCallback(GMM_CLIENT ClientType, GMM_DEVICE_CALLBACKS_INT *pDeviceCb, GMM_DDI_ALLOCATE *pAllocate);
+int GmmDeviceCallback(GMM_CLIENT ClientType, GMM_DEVICE_CALLBACKS_INT *pDeviceCb, GMM_DDI_DEALLOCATE *pDeallocate);
+int GmmDeviceCallback(GMM_CLIENT ClientType, GMM_DEVICE_CALLBACKS_INT *pDeviceCb, GMM_DDI_WAITFORSYNCHRONIZATIONOBJECTFROMCPU *pWait);
+
+int GmmCheckForNullDevCbPfn(GMM_CLIENT ClientType, GMM_DEVICE_CALLBACKS_INT *pDeviceCb, GMM_DEVICE_CALLBACKS_TYPE CallBackType);
+
+extern GMM_TRANSLATIONTABLE_CALLBACKS DummyTTCB;
+
+#endif /*__linux__*/
diff --git a/Source/inc/common/sku_wa.h b/Source/inc/common/sku_wa.h
index e9e46a7..e83c1a6 100644
--- a/Source/inc/common/sku_wa.h
+++ b/Source/inc/common/sku_wa.h
@@ -457,6 +457,24 @@
         WA_BUG_TYPE_CORRUPTION,
         WA_BUG_PERF_IMPACT_UNKNOWN, WA_COMPONENT_GMM)
 
+        WA_DECLARE(
+        WaAuxTable16KGranular,
+        "AuxTable map granularity changed to 16K ",
+        WA_BUG_TYPE_PERF,
+        WA_BUG_PERF_IMPACT_UNKNOWN, WA_COMPONENT_UNKNOWN)
+
+        WA_DECLARE(
+        WaLimit128BMediaCompr,
+        "WA to limit media decompression on Render pipe to 128B (2CLs) 4:n.",
+        WA_BUG_TYPE_FUNCTIONAL,
+        WA_BUG_PERF_IMPACT_UNKNOWN, WA_COMPONENT_GMM)
+
+        WA_DECLARE(
+        WaUntypedBufferCompression,
+        "WA to allow untyped raw buffer AuxTable mapping",
+        WA_BUG_TYPE_FUNCTIONAL,
+        WA_BUG_PERF_IMPACT_UNKNOWN, WA_COMPONENT_GMM)
+
 } WA_TABLE, *PWA_TABLE;
 
 //********************************** SKU/WA Macros *************************************