blob: fdab2b4c079c62565255d1946d116c8ec1dc5fd4 [file] [log] [blame]
/*
* Copyright (c) 2018-2020, 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.
*/
//!
//! \file mos_auxtable_mgr.cpp
//! \brief Container class for GMM aux table manager wrapper
//!
#include "mos_auxtable_mgr.h"
#include "mos_utilities.h"
//!
//! \brief Implementation of device callback for GMM PageTableMgr to allocate page table BO
//!
//! \param [in] bufMgr
//! MOS_BUFMGR pass to GMM PageTableMgr by media driver
//! \param [in] size
//! Size to be allocated
//! \param [in] alignment
//! Alignment requirement for the VA address of the allocated buffer
//! \param [out] bo
//! Poiner to the bo object allocated
//! \param [out] cpuAddr
//! CPU VA of the bo object allocated
//! \param [out] gpuAddr
//! CPU VA of the bo object allocated
//!
//! \return int
//! Error status code. 0 if success, else errno.
//!
static int AllocateCb(void *bufMgr, size_t size, size_t alignment, void **bo, void **cpuAddr, uint64_t *gpuAddr)
{
int ret = 0;
MOS_BUFMGR *bm;
void *userptr;
mos_linux_bo *lbo;
if (bufMgr == nullptr)
return -EINVAL;
bm = (MOS_BUFMGR *)bufMgr;
userptr = MOS_AlignedAllocMemory(size, alignment);
if (userptr == nullptr)
return -ENOMEM;
lbo = mos_bo_alloc_userptr(bm, "GmmAuxPageTable", userptr, I915_TILING_NONE, size, size, 0);
if (lbo == nullptr)
{
MOS_FreeMemory(userptr);
return -EAGAIN;
}
mos_bo_set_softpin(lbo);
*bo = lbo;
*cpuAddr = userptr;
*gpuAddr = (uint64_t)lbo->offset64;
return 0;
}
//!
//! \brief Implementation of device callback for GMM PageTableMgr to free allocated BO
//!
//! \param [in] bo
//! Poiner to the bo object to be freed
//!
//! \return none
//!
static void DeallocateCb(void *bo)
{
mos_linux_bo *lbo = (mos_linux_bo *)bo;
if (lbo != nullptr)
{
void* virt = lbo->virt;
mos_bo_wait_rendering(lbo);
mos_bo_unreference(lbo);
if (virt)
{
MOS_FreeMemory(virt);
}
}
}
//!
//! \brief Implementation of device callback for GMM PageTableMgr to wait BO idle
//!
//! \param [in] bo
//! Poiner to the bo object to be waited
//!
//! \return none
//!
static void WaitFromCpuCb(void *bo)
{
mos_linux_bo *lbo = (mos_linux_bo *)bo;
if (lbo != nullptr)
{
mos_bo_wait_rendering((mos_linux_bo *)bo);
}
}
AuxTableMgr::AuxTableMgr(MOS_BUFMGR *bufMgr)
{
if (bufMgr)
{
GMM_DEVICE_CALLBACKS_INT deviceCb = {0};
GmmExportEntries GmmFuncs;
GMM_STATUS gmmStatus = OpenGmm(&GmmFuncs);
if(gmmStatus != GMM_SUCCESS)
{
MOS_OS_ASSERTMESSAGE("gmm init failed.");
}
m_gmmClientContext = GmmFuncs.pfnCreateClientContext((GMM_CLIENT)GMM_LIBVA_LINUX);
if (m_gmmClientContext == nullptr)
{
MOS_OS_ASSERTMESSAGE(" nullptr returned by GmmCreateClientContext");
}
else
{
deviceCb.pBufMgr = bufMgr;
deviceCb.DevCbPtrs_.pfnAllocate = AllocateCb;
deviceCb.DevCbPtrs_.pfnDeallocate = DeallocateCb;
deviceCb.DevCbPtrs_.pfnWaitFromCpu = WaitFromCpuCb;
m_gmmPageTableMgr = m_gmmClientContext->CreatePageTblMgrObject(&deviceCb, AUXTT);
if (m_gmmPageTableMgr == nullptr)
{
MOS_OS_ASSERTMESSAGE(" nullptr returned by new GMM_PAGETABLE_MGR");
}
}
}
}
AuxTableMgr::~AuxTableMgr()
{
if (m_gmmPageTableMgr != nullptr)
{
m_gmmClientContext->DestroyPageTblMgrObject((GMM_PAGETABLE_MGR *)m_gmmPageTableMgr);
m_gmmPageTableMgr = nullptr;
}
if (m_gmmClientContext != nullptr)
{
GmmExportEntries GmmFuncs;
GMM_STATUS gmmStatus = OpenGmm(&GmmFuncs);
if(gmmStatus != GMM_SUCCESS)
{
MOS_OS_ASSERTMESSAGE("gmm init failed.");
}
GmmFuncs.pfnDeleteClientContext((GMM_CLIENT_CONTEXT *)m_gmmClientContext);
m_gmmClientContext = nullptr;
}
}
AuxTableMgr * AuxTableMgr::CreateAuxTableMgr(MOS_BUFMGR *bufMgr, MEDIA_FEATURE_TABLE *sku)
{
if (MEDIA_IS_SKU(sku, FtrE2ECompression) && !MEDIA_IS_SKU(sku, FtrFlatPhysCCS))
{
AuxTableMgr *auxTableMgr = MOS_New(AuxTableMgr, bufMgr);
if (auxTableMgr == nullptr)
{
MOS_OS_ASSERTMESSAGE(" nullptr returned by creating AuxTableMgr");
}
return auxTableMgr;
}
return nullptr;
}
MOS_STATUS AuxTableMgr::MapResource(GMM_RESOURCE_INFO *gmmResInfo, MOS_LINUX_BO *bo)
{
if (gmmResInfo == nullptr || bo == nullptr)
{
return MOS_STATUS_NULL_POINTER;
}
GMM_RESOURCE_FLAG flags = gmmResInfo->GetResFlags();
if ((flags.Info.MediaCompressed || flags.Info.RenderCompressed) &&
(flags.Gpu.MMC && flags.Gpu.CCS) &&
(bo->aux_mapped == false))
{
int ret = 0;
ret = mos_bo_set_softpin(bo);
if (ret != 0)
{
MOS_OS_ASSERTMESSAGE("Aux mapping failed: softpin failed");
return MOS_STATUS_UNKNOWN;
}
GMM_DDI_UPDATEAUXTABLE updateReq = {};
updateReq.BaseResInfo = gmmResInfo;
updateReq.BaseGpuVA = bo->offset64;
updateReq.Map = 1;
if (GMM_SUCCESS != ((GMM_PAGETABLE_MGR *)m_gmmPageTableMgr)->UpdateAuxTable(&updateReq))
{
MOS_OS_ASSERTMESSAGE("update AuxTable failed");
return MOS_STATUS_UNKNOWN;
}
bo->aux_mapped = true;
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS AuxTableMgr::UnmapResource(GMM_RESOURCE_INFO *gmmResInfo, MOS_LINUX_BO *bo)
{
if (gmmResInfo && bo && bo->aux_mapped)
{
GMM_DDI_UPDATEAUXTABLE updateReq = {};
MOS_OS_ASSERT(gmmResInfo->GetResFlags().Info.MediaCompressed ||
gmmResInfo->GetResFlags().Info.RenderCompressed);
updateReq.BaseResInfo = gmmResInfo;
updateReq.BaseGpuVA = bo->offset64;
updateReq.Map = 0;
((GMM_PAGETABLE_MGR*)m_gmmPageTableMgr)->UpdateAuxTable(&updateReq);
bo->aux_mapped = false;
}
return MOS_STATUS_SUCCESS;
}
MOS_STATUS AuxTableMgr::EmitAuxTableBOList(MOS_LINUX_BO *cmd_bo)
{
// Retrieve aux table bo list from GMM and emit it to exec buffer bo list
int boCnt = ((GMM_PAGETABLE_MGR*)m_gmmPageTableMgr)->GetNumOfPageTableBOs(AUXTT);
if (boCnt <= 0) {
return MOS_STATUS_SUCCESS;
}
mos_linux_bo **boList = (MOS_LINUX_BO **)MOS_AllocAndZeroMemory(boCnt * sizeof(mos_linux_bo*));
if (boList == nullptr)
return MOS_STATUS_NO_SPACE;
((GMM_PAGETABLE_MGR*)m_gmmPageTableMgr)->GetPageTableBOList(AUXTT, boList);
for (int i=0; i<boCnt; i++)
{
int ret = mos_bo_add_softpin_target(cmd_bo, boList[i], false);
if (ret != 0)
{
MOS_OS_ASSERTMESSAGE("Error patching alloc_bo = 0x%x, cmd_bo = 0x%x.",
(uintptr_t)boList[i],
(uintptr_t)cmd_bo);
return MOS_STATUS_UNKNOWN;
}
}
MOS_FreeMemory(boList);
return MOS_STATUS_SUCCESS;
}
uint64_t AuxTableMgr::GetAuxTableBase()
{
return m_gmmPageTableMgr ? ((GMM_PAGETABLE_MGR*)m_gmmPageTableMgr)->GetAuxL3TableAddr() : 0;
}